1. jiffies
头文件 <linux/jiffies.h>
通常是 unsigned long
格式 64位,也可能是32位(在32位机器上),表示系统最近一次启动到当前的时间间隔。
2. HZ
HZ表示每秒产生的时钟滴答数; HZ 是一个体系依赖的值,在<linux/param.h>
中定义或该文件包含的某个子平台相关文件中。
它与内核源码目录的”.config”里的”CONFIG_HZ”的值有关, 通常值为200, 服务器的值为1000.
在.config
里它的值为”CONFIG_HZ=100”, 表示此HZ定时器每秒钟触发100次,每次间隔10ms.
在ARM下,HZ的定义如下:
#ifdef __KERNEL__
# define HZ CONFIG_HZ /* Internal kernel timer frequency */
# define USER_HZ 100 /* 用户空间使用的HZ,User interfaces are in "ticks" */
# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
#else
# define HZ 100
#endif
也就是说:HZ 由KERNEL和CONFIG_HZ决定。 若未定义 KERNEL
,HZ为100;否则为 CONFIG_HZ
。
而CONFIG_HZ
是在内核的根目录的.config
文件中定义,并没有在make menuconfig
的配置选项中出现。
例如:在\arch\arm\configs\s3c2410_defconfig
配置文件中定义:
# Kernel Features
#
# CONFIG_PREEMPT is not set
# CONFIG_NO_IDLE_HZ is not set
CONFIG_HZ=200
内核定时器
内核定时器用于在未来某个时间点,调度执行某个函数,在这个时间点到来之前不会阻塞当前进程。
内核定时器就是一个数据结构,告诉内核在用户定义的时间点,使用用户定义的参数,执行用户定义的函数。
实现在<Linux/timer.h> 和 kernel/timer.c
被定时器调度运行的函数几乎不会再注册这个函数的进程正在运行的时候执行,所以是异步操作; 这种异步操作类似“软中断”,所以必须满足下面的要求:
- 没有 current 指针、不允许访问用户空间。因为没有进程上下文,相关代码和被中断的进程没有任何联系。
- 不能执行休眠(或可能引起休眠的函数)和调度。
- 任何被访问的数据结构都应该针对并发访问进行保护,以防止竞争条件。
注意: 内核代码可以通过in_interrupt()
来判断是否在中断上下文,这个函数没有参数,返回非零表示在中断上下文。
内核定时器API
struct timer_list {
struct list_head entry; //指向下一个定时器对象
unsigned long expires; //表示定时器的到期时间,也就是当jiffies的值与expires的值相等时,触发调用function函数.
void (*function)(unsigned long); //定时器超时调用的函数
unsigned long data; // function函数的参数
...
};
expires字段表示期望定时器执行的jiffies值;到达该jiffies值时,调用function函数,并传递data作为参数。
**注意: :如果需要传入多个参数,可以将多个参数捆绑成数据结构,然后将数据结构指针强制转化成 unsigned long 格式传入。**
用法:
1). 初始化timer_list对象的成员
init_timer(&timer);
timer.function = func;
timer.data = data;
2). 增加到内核里的定时器链表里.
add_timer(&timer);
或者用mod_timer(&timer, expires) //当定时器对象还没加入定时链表里会自动加入,并且可修改定时的到期时间.
3). 定时器对象使用完后,需要从定时器链表里移除.
del_timer(&timer);
定时器代码示例:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/timer.h>
struct timer_list mytimer;
void timer_func(unsigned long data)
{
printk("timer time out ...%ld\n", data);
//1ms 后再次触发
mytimer.data += 1;
mod_timer(&mytimer, jiffies + HZ/1000);
}
static int __init test_init(void)
{
init_timer(&mytimer);
mytimer.function = timer_func;
mytimer.data = 0;
mytime。expires = jiffies + HZ/1000 ; //1ms 以后触发 timer_func 函数
return 0;
}
static void __exit test_exit(void)
{
del_timer(&mytimer);
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");