当前位置:首页 » 操作系统 » linuxjiffies

linuxjiffies

发布时间: 2023-02-17 21:11:48

linux内核获取时间问题

1 tv_usec是微秒,变小是因为秒进位了,你要同时把秒输出就能看出来了
2 有个常量HZ 它和jiffies是互为倒数. 以前一直是100, 也就是1秒100下,就是1个j=10毫秒
如今也有更快的,比如1000.但是在用户空间,一直是100.

所以jiffies非常快,会容易溢出, 例如一个无符号整形存储秒,那么69年左右会溢出
毫秒的话要除1000, 不到一个月就溢出了.而电脑的运行时间是完全可以达到这么久不重启的.
jiffies_64就不用担心这个问题了.

3可参加linux/time.h中提供的api,精确到微秒

Ⅱ Linux Kernel 2.4 和 2.6 的区别

1、 使用新的入口
必须包含 <linux/init.h>
mole_init(your_init_func);
mole_exit(your_exit_func);
老版本:int init_mole(void);
void cleanup_mole(voi);
2.4中两种都可以用,对如后面的入口函数不必要显示包含任何头文件。
2、 GPL
MODULE_LICENSE("Dual BSD/GPL");
老版本:MODULE_LICENSE("GPL");
3、 模块参数
必须显式包含<linux/moleparam.h>
mole_param(name, type, perm);
mole_param_named(name, value, type, perm);
参数定义
mole_param_string(name, string, len, perm);
mole_param_array(name, type, num, perm);
老版本:MODULE_PARM(variable,type);
MODULE_PARM_DESC(variable,type);
4、 模块别名
MODULE_ALIAS("alias-name");
这是新增的,在老版本中需在/etc/moles.conf配置,现在在代码中就可以实现。
5、 模块计数
int try_mole_get(&mole);
mole_put();
老版本:MOD_INC_USE_COUNT 和 MOD_DEC_USE_COUNT
6、 符号导出
只有显示的导出符号才能被其他 模块使用,默认不导出所有的符号,不必使用EXPORT_NO
_SYMBOLS
老板本:默认导出所有的符号,除非使用EXPORT_NO_SYMBOLS
7、 内核版本检查
需要在多个文件中包含<linux/mole.h>时,不必定义__NO_VERSION__
老版本:在多个文件中包含<linux/mole.h>时,除在主文件外的其他文件中必须定义_
_NO_VERSION__,防止版本重复定义。
8、 设备号
kdev_t被废除不可用,新的dev_t拓展到了32位,12位主设备号,20位次设备号。
unsigned int iminor(struct inode *inode);
unsigned int imajor(struct inode *inode);
老版本:8位主设备号,8位次设备号
int MAJOR(kdev_t dev);
int MINOR(kdev_t dev);
9、 内存分配头文件变更
所有的内存分配函数包含在头文件<linux/slab.h>,而原来的<linux/malloc.h>不存在
老版本:内存分配函数包含在头文件<linux/malloc.h>
10、 结构体的初试化
gcc开始采用ANSI C的struct结构体的初始化形式:
static struct some_structure = {
.field1 = value,
.field2 = value,
..
};
老版本:非标准的初试化形式
static struct some_structure = {
field1: value,
field2: value,
..
};
11、 用户模式帮助器
int call_usermodehelper(char *path, char **argv, char **envp,
int wait);
新增wait参数
12、 request_mole()
request_mole("foo-device-%d", number);
老版本:
char mole_name[32];
printf(mole_name, "foo-device-%d", number);
request_mole(mole_name);
13、 dev_t引发的字符设备的变化
1、取主次设备号为
unsigned iminor(struct inode *inode);
unsigned imajor(struct inode *inode);
2、老的register_chrdev()用法没变,保持向后兼容,但不能访问设备号大于256的设备

3、新的接口为
a)注册字符设备范围
int register_chrdev_region(dev_t from, unsigned count, char *name);
b)动态申请主设备号
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, char
*name);
看了这两个函数郁闷吧^_^!怎么和file_operations结构联系起来啊?别急!
c)包含 <linux/cdev.h>,利用struct cdev和file_operations连接
struct cdev *cdev_alloc(void);
void cdev_init(struct cdev *cdev, struct file_operations *fops);
int cdev_add(struct cdev *cdev, dev_t dev, unsigned count);
(分别为,申请cdev结构,和fops连接,将设备加入到系统中!好复杂啊!)
d)void cdev_del(struct cdev *cdev);
只有在cdev_add执行成功才可运行。
e)辅助函数
kobject_put(&cdev->kobj);
struct kobject *cdev_get(struct cdev *cdev);
void cdev_put(struct cdev *cdev);
这一部分变化和新增的/sys/dev有一定的关联。
14、 新增对/proc的访问操作
<linux/seq_file.h>
以前的/proc中只能得到string, seq_file操作能得到如long等多种数据。
相关函数:
static struct seq_operations 必须实现这个类似file_operations得数据中得各个成
员函数。
seq_printf();
int seq_putc(struct seq_file *m, char c);
int seq_puts(struct seq_file *m, const char *s);
int seq_escape(struct seq_file *m, const char *s, const char *esc);
int seq_path(struct seq_file *m, struct vfsmount *mnt,
struct dentry *dentry, char *esc);
seq_open(file, &ct_seq_ops);
等等
15、 底层内存分配
1、<linux/malloc.h>头文件改为<linux/slab.h>
2、分配标志GFP_BUFFER被取消,取而代之的是GFP_NOIO 和 GFP_NOFS
3、新增__GFP_REPEAT,__GFP_NOFAIL,__GFP_NORETRY分配标志
4、页面分配函数alloc_pages(),get_free_page()被包含在<linux/gfp.h>中
5、对NUMA系统新增了几个函数:
a) struct page *alloc_pages_node(int node_id,
unsigned int gfp_mask,
unsigned int order);
b) void free_hot_page(struct page *page);
c) void free_cold_page(struct page *page);
6、 新增Memory pools
<linux/mempool.h>
mempool_t *mempool_create(int min_nr,
mempool_alloc_t *alloc_fn,
mempool_free_t *free_fn,
void *pool_data);
void *mempool_alloc(mempool_t *pool, int gfp_mask);
void mempool_free(void *element, mempool_t *pool);
int mempool_resize(mempool_t *pool, int new_min_nr, int gfp_mask);
16、 per-CPU变量
get_cpu_var();
put_cpu_var();
void *alloc_percpu(type);
void free_percpu(const void *);
per_cpu_ptr(void *ptr, int cpu)
get_cpu_ptr(ptr)
put_cpu_ptr(ptr)
老版本使用
DEFINE_PER_CPU(type, name);
EXPORT_PER_CPU_SYMBOL(name);
EXPORT_PER_CPU_SYMBOL_GPL(name);
DECLARE_PER_CPU(type, name);
DEFINE_PER_CPU(int, mypcint);
2.6内核采用了可剥夺得调度方式这些宏都不安全。
17、 内核时间变化
1、现在的各个平台的HZ为
Alpha: 1024/1200; ARM : 100/128/200/1000; CRIS: 100; i386: 1000; IA-64:
1024; M68K: 100; M68K-nommu: 50-1000; MIPS: 100/128/1000; MIPS64: 100;
PA-RISC: 100/1000; PowerPC32: 100; PowerPC64: 1000; S/390: 100; SPARC32:
100; SPARC64: 100; SuperH: 100/1000; UML: 100; v850: 24-100; x86-64: 1000.
2、由于HZ的变化,原来的jiffies计数器很快就溢出了,引入了新的计数器jiffies_64
3、#include <linux/jiffies.h>
u64 my_time = get_jiffies_64();
4、新的时间结构增加了纳秒成员变量
struct timespec current_kernel_time(void);
5、他的timer函数没变,新增
void add_timer_on(struct timer_list *timer, int cpu);
6、新增纳秒级延时函数
ndelay();
7、POSIX clocks 参考kernel/posix-timers.c
18、 工作队列(workqueue)
1、任务队列(task queue )接口函数都被取消,新增了workqueue接口函数
struct workqueue_struct *create_workqueue(const char *name);
DECLARE_WORK(name, void (*function)(void *), void *data);
INIT_WORK(struct work_struct *work,
void (*function)(void *), void *data);
PREPARE_WORK(struct work_struct *work,
void (*function)(void *), void *data);
2、申明struct work_struct结构
int queue_work(struct workqueue_struct *queue,
struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *queue,
struct work_struct *work,
unsigned long delay);
int cancel_delayed_work(struct work_struct *work);
void flush_workqueue(struct workqueue_struct *queue);
void destroy_workqueue(struct workqueue_struct *queue);
int schele_work(struct work_struct *work);
int schele_delayed_work(struct work_struct *work, unsigned long
delay);
19、 新增创建VFS的"libfs"
libfs给创建一个新的文件系统提供了大量的API.
主要是对struct file_system_type的实现。
参考源代码:
drivers/hotplug/pci_hotplug_core.c
drivers/usb/core/inode.c
drivers/oprofile/oprofilefs.c
fs/ramfs/inode.c
fs/nfsd/nfsctl.c (simple_fill_super() example)

Ⅲ 有没有办法可以获取linux开发板的硬件定时器频率

1、默认情况下系统节拍率选择100Hz。
2、设置好后在Linux内核源码根目录下的config文件中可见系统节拍率被设置为100Hz。
3、Linux内核会使用CONFIGHZ来设置自己的系统时钟,文件includeasmgenericparamh。
4、Linux内核使用全局变量jiffies来记录系统从启动以来的系统节拍数,系统启动的时候会将jiffies初始化为0,即可获取,linux开发板的硬件定时器频率。

Ⅳ Linux 这个定时器每个部分的语句是什么意思呢

地址
(unsigned long *)&jiffies
将上一步取到的地址强制类型转换为指向“无符号长整形 ”这种数据类型的指针
*(unsigned long *)&jiffies
读取上一步得到的指针所指向的值
(*(unsigned long *)&jiffies)++;
将上一步得到的值进行自加操作(也就是加1)

Ⅳ 在Linux环境下编程,需要用到jiffies变量,想请问使用jiffies应该引入哪个头文件

jiffies定义在文件<linux/jiffies.h>中:
extern unsigned long volatile jiffies;

Ⅵ linux 下编译WIFI错误怎么改

include/asm/memory.h:170: error: `PHYS_OFFSET' undeclared (first use in this function)
include/asm/memory.h:170: error: (Each undeclared identifier is reported only once
include/asm/memory.h:170: error: for each function it appears in.)
这很明显的告诉你,有没有定义的宏

Ⅶ 在linux环境下,我们使用C语言编程,如何正确计算CPU使用率(不限/proc/stat)

我的笨方法:
以/proc/stat为例,它里面的内容如下:(第一行的几个单词,是我为了便于说明,另外标注的)
user nice system idle iowait irq softirq
cpu 65376847 362756 2405159 10834971593 3765180 93399 2395097 0
cpu0 7680302 5263 111909 1355640955 47680 0 185343 0
cpu1 6527638 2261 327795 1356540189 249151 1 24242 0
intr 21259182 122 97003 0 0 0 0 0 0 1 44 0 0 4290639 0 0 0 742540 1330673 0 0 0 0 0 111 173 0 0 0 0 161039 191398 10286 2440 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 42582486
btime 1376534806
processes 346513
procs_running 1
procs_blocked 0
softirq 21851001 2 9105868 18006 318205 256633 2 1384334 1159984 60546 9547421
---------------------------- 分割线------------------------------
说明:
user:从系统启动开始累计到当前时刻,用户态的CPU时间(单位:jiffies) ,不包含 nice值为负进程。1jiffies=0.01秒
nice:从系统启动开始累计到当前时刻,nice值为负的进程所占用的CPU时间(单位:jiffies)
system:从系统启动开始累计到当前时刻,核心时间(单位:jiffies)
idle:从系统启动开始累计到当前时刻,除硬盘IO等待时间以外其它等待时间(单位:jiffies)
iowait:从系统启动开始累计到当前时刻,硬盘IO等待时间(单位:jiffies) ,
irq:从系统启动开始累计到当前时刻,硬中断时间(单位:jiffies)
softirq:从系统启动开始累计到当前时刻,软中断时间(单位:jiffies)
CPU时间=user+system+nice+idle+iowait+irq+softirq
-------------------------下面这几项可以不看------------------
intr:第一个为自系统启动以来,发生的所有的中断的次数;然后每个数对应一个特定的中断自系统启动以来所发生的次数。
ctxt:自系统启动以来CPU发生的上下文交换的次数。
btime:从系统启动到现在为止的时间,单位为秒。
processes:自系统启动以来所创建的任务的个数目。
procs_running:当前运行队列的任务的数目。
procs_blocked:当前被阻塞的任务的数目。
-----------------------------计算方法-----------------------------
那么CPU利用率可以使用以下两个方法。先取两个采样点,然后计算其差值:
cpu usage=(idle2-idle1)/(cpu2-cpu1)*100
cpu usage=[(user_2 +sys_2+nice_2) - (user_1 + sys_1+nice_1)]/(total_2 - total_1)*100
=============================================
建议:要用C语言来编程实现的话,提取各项数据会比较复杂,而用shell脚本来提取的话,会简单的多;所以你可以尝试用脚本来提取数据并计算出CPU使用率,然后在C程序中用system( )函数来调用这个脚本。

Ⅷ linux 时钟中断 哪个定时器

一. Linux的硬件时间
PC机中的时间有三种硬件时钟实现,这三种都是基于晶振产生的方波信号输入。这三种时钟为:(1)实时时钟RTC ( Real Time Clock) (2)可编程间隔器PIT(Programmable Interval Timer )(3)时间戳计数器TSC(Time Stamp Clock)
1. 实时时钟 RTC
用于长时间存放系统时间的设备,即时关机后也可依靠主板CMOS电池继续保持系统的计时,原理图如下:

Note: Linux与RTC的关系是,当Linux启动时从RTC读取时间和日期的基准值,然后在Kernel运行期间便抛开RTC,以软件的形式维护系统的时间日期,并在适当时机由Kernel将时间写回RTC Register.
1.1 RTC Register
(1). 时钟与日历Register
共10个,地址:0x00-0x09,分别用于保存时间日历的具体信息,详情如下:
00 Current Second for RTC
01 Alarm Second
02 Current Minute
03 Alarm Minute
04 Current Hour
05 Alarm Hour
06 Current Day of Week(1=Sunday)
07 Current Date of Month
08 Current Month
09 Current Year
(2).状态和控制Register
共四个,地址:0x0a-0x0d,控制RTC芯片的工作方式,并表示当前状态。
l 状态RegisterA , 0x0A 格式如下:
bit[7]——UIP标志(Update in Progress),为1表示RTC正在更新日历寄存器组中的值,此时日历寄存器组是不可访问的(此时访问它们将得到一个无意义的渐变值)。
bit[6:4]——这三位是用来定义RTC的操作频率。各种可能的值如下:

DV2 DV1 DV0
0 0 0 4.194304 MHZ
0 0 1 1.048576 MHZ
0 1 0 32.769 KHZ
1 1 0/1 任何
PC机通常设置成“010”。
bit[3:0]——速率选择位(Rate Selection bits),用于周期性或方波信号输出。
RS3 RS2 RS1 RS0 周期性中断 方波 周期性中断 方波
0 0 0 0 None None None None
0 0 0 1 30.517μs 32.768 KHZ 3.90625ms 256 HZ
0 0 1 0 61.035μs 16.384 KHZ
0 0 1 1 122.070μs 8.192KHZ
0 1 0 0 244.141μs 4.096KHZ
0 1 0 1 488.281μs 2.048KHZ
0 1 1 0 976.562μs 1.024KHZ
0 1 1 1 1.953125ms 512HZ
1 0 0 0 3.90625ms 256HZ
1 0 0 1 7.8125ms 128HZ
1 0 1 0 15.625ms 64HZ
1 0 1 1 31.25ms 32HZ
1 1 0 0 62.5ms 16HZ
1 1 0 1 125ms 8HZ
1 1 1 0 250ms 4HZ
1 1 1 1 500ms 2HZ
PC机BIOS对其默认的设置值是“0110”
l 状态Register B , 0x0B 格式如下:
bit[7]——SET标志。为1表示RTC的所有更新过程都将终止,用户程序随后马上对日历寄存器组中的值进行初始化设置。为0表示将允许更新过程继续。
bit[6]——PIE标志,周期性中断enable标志。
bit[5]——AIE标志,告警中断enable标志。
bit[4]——UIE标志,更新结束中断enable标志。
bit[3]——SQWE标志,方波信号enable标志。
bit[2]——DM标志,用来控制日历寄存器组的数据模式,0=BCD,1=BINARY。BIOS总是将它设置为0。
bit[1]——24/12标志,用来控制hour寄存器,0表示12小时制,1表示24小时制。PC机BIOS总是将它设置为1。
bit[0]——DSE标志。BIOS总是将它设置为0。
l 状态Register C,0x0C 格式如下:
bit[7]——IRQF标志,中断请求标志,当该位为1时,说明寄存器B中断请求 发生。
bit[6]——PF标志,周期性中断标志,为1表示发生周期性中断请求。
bit[5]——AF标志,告警中断标志,为1表示发生告警中断请求。
bit[4]——UF标志,更新结束中断标志,为1表示发生更新结束中断请求。
l 状态Register D,0x0D 格式如下:
bit[7]——VRT标志(Valid RAM and Time),为1表示OK,为0表示RTC 已经掉电。
bit[6:0]——总是为0,未定义。
2.可编程间隔定时器 PIT
每个PC机中都有一个PIT,以通过IRQ0产生周期性的时钟中断信号,作为系统定时器 system timer。当前使用最普遍的是Intel 8254 PIT芯片,它的I/O端口地址是0x40~0x43。
Intel 8254 PIT有3个计时通道,每个通道都有其不同的用途:
(1) 通道0用来负责更新系统时钟。每当一个时钟滴答过去时,它就会通过IRQ0向 系统 产生一次时钟中断。
(2) 通道1通常用于控制DMAC对RAM的刷新。
(3) 通道2被连接到PC机的扬声器,以产生方波信号。
每 个通道都有一个向下减小的计数器,8254 PIT的输入时钟信号的频率是1.193181MHZ,也即一秒钟输入1193181个clock-cycle。每输入一个clock-cycle其时间 通道的计数器就向下减1,一直减到0值。因此对于通道0而言,当他的计数器减到0时,PIT就向系统产生一次时钟中断,表示一个时钟滴答已经过去了。计数 器为16bit,因此所能表示的最大值是65536,一秒内发生的滴答数是:1193181/65536=18.206482.
PIT的I/O端口:
0x40 通道0 计数器 Read/Write
0X41 通道1计数器 Read/Write
0X42 通道2计数器 Read/Write
0X43 控制字 Write Only
Note: 因PIT I/O端口是8位,而PIT相应计数器是16位,因此必须对PIT计数器进行两次读写。
8254 PIT的控制寄存器(0X43)的格式如下:
bit[7:6] — 通道选择位:00 ,通道0;01,通道1;10,通道2;11,read-back command,仅8254。
bit[5:4] – Read/Write/Latch锁定位,00,锁定当前计数器以便读取计数值;01,只读高字节;10,只读低字节;11,先高后低。
bit[3:1] – 设定各通道的工作模式。
000 mode0 当通道处于count out 时产生中断信号,可用于系统定时
001 mode1 Hardware retriggerable one-shot
010 mode2 Rate Generator。产生实时时钟中断,通道0通常工作在这个模式下
011 mode3 方波信号发生器
100 mode4 Software triggered strobe
101 mode5 Hardware triggered strobe
3. 时间戳计数器 TSC
从Pentium开始,所有的Intel 80x86 CPU就都包含一个64位的时间戳记数器(TSC)的寄存器。该寄存器实际上是一个不断增加的计数器,它在CPU的每个时钟信号到来时加1(也即每一个clock-cycle输入CPU时,该计数器的值就加1)。
汇编指令rdtsc可以用于读取TSC的值。利用CPU的TSC,操作系统通常可以得到更为精准的时间度量。假如clock-cycle的频率是400MHZ,那么TSC就将每2.5纳秒增加一次。
二. Linux时钟中断处理程序
1. 几个概念
(1)时钟周期(clock cycle)的频率:8253/8254 PIT的本质就是对由晶体振荡器产生的时钟周期进行计数,晶体振荡器在1秒时间内产生的时钟脉冲个数就是时钟周期的频率。Linux用宏 CLOCK_TICK_RATE来表示8254 PIT的输入时钟脉冲的频率(在PC机中这个值通常是1193180HZ),该宏定义在include/asm-i386/timex.h头文件中
#define CLOCK_TICK_RATE 1193180 kernel=2.4 &2.6

(2)时钟滴答(clock tick):当PIT通道0的计数器减到0值时,它就在IRQ0上产生一次时钟中断,也即一次时钟滴答。PIT通道0的计数器的初始值决定了要过多少时钟周期才产生一次时钟中断,因此也就决定了一次时钟滴答的时间间隔长度。
(3)时钟滴答的频率(HZ):1秒时间内PIT所产生的时钟滴答次数。 这个值也由PIT通道0的计数器初值决定的.Linux内核用宏HZ来表示时钟滴答的频率,而且在不同的平台上HZ有不同的定义值。对于ALPHA和 IA62平台HZ的值是1024,对于SPARC、MIPS、ARM和i386等平台HZ的值都是100。该宏在i386平台上的定义如下 (include/asm-i386/param.h):
#define HZ 100 kernel=2.4
#define HZ CONFIG_HZ kernel=2.6

(4)宏LATCH:定义要写到PIT通道0的计数器中的值,它表示PIT将隔多少个时钟周期产生一次时钟中断。公式计算:
LATCH=(1秒之内的时钟周期个数)÷(1秒之内的时钟中断次数)=(CLOCK_TICK_RATE)÷(HZ)
定义在<include/linux/timex.h>
#define LATCH ((CLOCK_TICK_RATE + HZ/2) / HZ)
(5)全局变量jiffies:用于记录系统自启动以来产生的滴答总数。启动时,kernel将该变量初始为0,每次时钟中断处理程序timer_interrupt()将该变量加1。因为一秒钟内增加的时钟中断次数等于Hz,所以jiffies一秒内增加的值也是Hz。由此可得系统运行时间是jiffies/Hz 秒。
jiffies定义于<linux/jiffies.h>中:
extern unsigned long volatile jiffies;
Note:在kernel 2.4,jiffies是32位无符号数;kernel 2.6,jiffies是64位无符号数。
(6)全局变量xtime: 结构类型变量,用于表示当前时间距UNIX基准时间1970-01-01 00:00:00的相对秒数值。当系统启动时,Kernel通过读取RTC Register中的数据来初始化系统时间(wall_time),该时间存放在xtime中。
void __init time_init (void) {
... ...
xtime.tv_sec = get_cmos_time ();
xtime.tv_usec = 0;
... ... }
Note:实时时钟RTC的最主要作用便是在系统启动时用来初始化xtime变量。
2.Linux的时钟中断处理程序
Linux下时钟中断处理由time_interrupt() 函数实现,主要完成以下任务:
l 获得xtime_lock锁,以便对访问的jiffies_64 (kernel2.6)和 xtime进行保护
l 需要时应答或重新设置系统时钟。
l 周期性的使用系统时间(wall_time)更新实时时钟RTC
l 调用体系结构无关的时钟例程:do_timer()。
do_timer()主要完成以下任务:
l 更新jiffies;
l 更新系统时间(wall_time),该时间存放在xtime变量中
l 执行已经到期的动态定时器
l 计算平均负载值
void do_timer(unsigned long ticks)
{
jiffies_64 += ticks;
update_process_times(user_mode(regs));
update_times (ticks);
}
static inline void update_times(unsigned long ticks)
{
update_wall_time ();
calc_load (ticks);
}
time_interrupt ():

static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
int count;
write_lock (&xtime_lock); //获得xtime_lock锁

if(use_cyclone)
mark_timeoffset_cyclone();
else if (use_tsc) {
rdtscl(last_tsc_low); //读TSC register到last_tsc_low
spin_lock (&i8253_lock); //对自旋锁i8253_lock加锁,对8254PIT访问
outb_p (0x00, 0x43);

count = inb_p(0x40);
count |= inb(0x40) << 8;
if (count > LATCH) {
printk (KERN_WARNING "i8253 count too high! resetting../n");
outb_p (0x34, 0x43);
outb_p (LATCH & 0xff, 0x40);
outb(LATCH >> 8, 0x40);
count = LATCH - 1;
}
spin_unlock (&i8253_lock);

if (count = = LATCH) {
count- -;
}

count = ((LATCH-1) - count) * TICK_SIZE;
delay_at_last_interrupt = (count + LATCH/2) / LATCH;
} //end use_tsc
do_timer_interrupt (irq, NULL, regs);
write_unlock(&xtime_lock);
}//end time_interrupt

do_timer_interrupt():
static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
……
do_timer(regs);
if((time_status & STA_UNSYNC)= =0&&xtime.tv_sec> last_rtc_update + 660 && xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 && xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
if (set_rtc_mmss(xtime.tv_sec) == 0)
last_rtc_update = xtime.tv_sec;
else
last_rtc_update = xtime.tv_sec - 600;
……
}
do_timer_interrupt()主要完成:调用do_timer()和判断是否需要更新CMOS时钟。更新CMOS时钟的条件如下:三个须同时成立
1.系统全局时间状态变量time_status中没有设置STA_UNSYNC标志,即Linux没有设置外部同步时钟(如NTP)
2.自从上次CMOS时钟更新已经过去11分钟。全局变量last_rtc_update保存上次更新CMOS时钟的时间.
3.由于RTC存在Update Cycle,因此应在一秒钟间隔的中间500ms左右调用set_rtc_mmss()函数,将当前时间xtime.tv_sec写回RTC中。
Note. Linux kernel 中定义了一个类似jiffies的变量wall_jiffies,用于记录kernel上一次更新xtime时,jiffies的值。

Summary: Linux kernel在启动时,通过读取RTC里的时间日期初始化xtime,此后由kernel通过初始PIT来提供软时钟。
时钟中断处理过程可归纳为:系统时钟system timer在IRQ0上产生中断;kernel调用time_interrupt();time_interrupt()判断系统是否使用TSC,若使用 则读取TSC register;然后读取PIT 通道0的计数值;调用do_time_interrupt(),实现系统时间更新.

Ⅸ 内核定时器 jiffies的时间是多少

首先,你这样问,说明你不理解jiffies,jiffies应该说不是时间,jiffies的增加,是根据HZ的值变化而变化的。以时下linux kernel来说:1s=jiffies/HZ(即1秒=jiffies/HZ);在asm_i386中,HZ被定义为一个常,且为1000.一般在内核中定义超时是这样用,如:xxx_timer.expires = jiffies+HZ/100;这个定义表示超时时间为10ms,如果超过个时间就处理中断函数或者做你想做的事.当然HZ的分母你可以定为别的数。如HZ/1000等.

Ⅹ 有谁会用linux里面的定时器timer_list

这段代码是Linux的一个内核模块程序,timer_list也是Linux内核中的数据结构。模块程序不是以main函数作为入口的。而是以mole_init指定。
mole_init/mole_exit分别用于指定模块的加载和卸载函数。
加载模块(insmod)时,会调用mytimer_init函数。这个函数设置一个定时器,在定时器超时时执行myfunc函数,指定函数参数为“Hello,world!”。
myfunc执行时,会输出“Hello,world!”,mod_timer函数会将定时器重新计时,两秒后到期。

因此整个代码执行起来后的现象就是每两秒输出一次Hello,world!

热点内容
电脑服务器忙原因 发布:2025-07-30 13:35:29 浏览:839
linuxipmac 发布:2025-07-30 13:18:48 浏览:318
微信小程序开发源码 发布:2025-07-30 13:08:39 浏览:63
求累加和c语言 发布:2025-07-30 12:56:03 浏览:49
asp在线加密 发布:2025-07-30 12:51:06 浏览:937
java完全手册 发布:2025-07-30 12:22:05 浏览:614
支付宝接口java 发布:2025-07-30 12:21:58 浏览:76
做脚本需要把主机零件拆了吗 发布:2025-07-30 12:02:55 浏览:493
邮政解压视频完整版 发布:2025-07-30 12:00:54 浏览:491
301重定向php 发布:2025-07-30 11:52:34 浏览:22