28.1序言
Linux内核定时器用于处理指定时间后linux 内核 定时器,执行某个动作的。其特征如下:
(1)执行了一次便不会再度执行,处理后即失效;
(2)执行的动作函数中,不容许休眠和发生调度行为;
(3)应当对被访问的数据结构进行条件设置避免被调度;
在Linux内核定时器中,不得不说的一个东西就是jiffies。jiffies是记录着从笔记本开机到现今总共的时钟中断次数,Linux系统时钟频度是一个常数HZ来决定的,1秒内时钟中断的次数等于Hz,所以jiffies1秒内降低的值也就是Hz,一般HZ=100,精度就是10ms,所以通常来说Linux的精确度是10纳秒。假如我们要进行秒定时操作,需设置expire=jiffies+xs*HZ
28.2定时器数据结构
Linux内核管理着一个定时器队列,用户新增加一个定时器还会添加到队列中。通常是定义一个新的定时器结构linux 内核 定时器,之后填充好反弹函数等相关参数linux系统安装,添加到Linux定时器中断处理数组中,当Linux计时时间抵达用户所设置的定时时,这么将会执行用户所设置的操作反弹函数。
struct timer_list {
structlist_head entry; //timer双向链表
unsignedlong expires; //timer超时变量
void(*function)(unsigned long); //timer超时回调函数 www.linuxidc.com
unsignedlong data; //传递给回调函数的数据,也就是定时器数据
struct tvec_base *base; //timer base向量表用于timer_list的挂载和链表管理
//timer的一些扩展参数
……………
};
28.3相关函数说明
structtimer_listtm
定时器数据结构
init_timer(*tm)
初始化定时器结构;tm定时器数据结构表针
add_timer(*tm)
添加定时器;tm定时器结构表针
mod_timer(*tm,expire)
更改定时器;tm定时器数据结构;expire超时时间linux压缩命令,通常jiffies+xs
del_timer(*tm)
删掉定时器;tm定时器数据结构表针
定时器的使用步骤为:初始化定时器结构、定时器数据结构复制、添加定时器、编写定时器反弹函数、删除定时器。
28.4内核定时器实例
#include
#include
#include
#include
#include
#define I_DEVICE_NAME "iTimer"
static int major;
static struct timer_list tm;
void iTimer_callback(unsigned long arg)
{
struct timeval tv;
char *strp = (char*)arg;
printk(KERN_EMERG "%s: %lu, %sn", __func__, jiffies, strp);
mod_timer(&tm,jiffies+2*HZ); //使用mod_timer或再次add_timer函数重新触发
//tm.expires = jiffies+1*HZ;
//add_timer(&tm);
}
static int iopen(struct inode *pnode, struct file *pfile)
{
return 0;
}
static int iRead(struct file * file, const char __user * buffer, size_t count, loff_t * ppos)
{
return 0;
}
static const struct file_operations stfops = {
.owner = THIS_MODULE,
.read = iRead,
.open = iopen,
};
static int __init iTest_Init(void)
{
/* 主设备号设置为0表示由系统自动分配主设备号 */
major = register_chrdev(0, I_DEVICE_NAME, &stfops);
init_timer(&tm);
tm.function= iTimer_callback;
tm.data = (unsigned long)"I am timer";
tm.expires = jiffies+1*HZ;
add_timer(&tm);
return 0;
}
static void __exit iTest_Exit(void)
{
unregister_chrdev(major, I_DEVICE_NAME);
del_timer(&tm);
}
module_init(iTest_Init);
module_exit(iTest_Exit);
MODULE_LICENSE("GPL");