Linux Kernel 学习笔记12:定时任务 | 您所在的位置:网站首页 › 电话打不停的软件 › Linux Kernel 学习笔记12:定时任务 |
(本章基于:Linux-4.4.0-37) 内核定时器可在用户设定时间到达后调用一段任务,基本数据定义、API如下: struct timer_list { unsigned long expires; void (*function)(unsigned long); unsigned long data; ...... ...... }; 定时器基本数据类型,expires表明定时器期望jiffies所达到的值,当时间达到此值,将会调用function函数,并使用data作为参数; void init_timer(struct timer_list *timer) 初始化定时器 int add_timer(struct timer_list *timer) 添加一个定时器到内核动态定时器链表 int del_timer(struct timer_list *timer) 注销一个定时器 int del_timer_sync(struct timer_list *timer) 和del_timer相似,但它保证在返回时,定时器函数不在任何一个CPU上执行。del_timer_sync用来避免竞争情况在SMP系统上,并在UP内核中和del_timer相同。应当优先使用del_timer_sync; int mod_timer(struct timer_list *timer) 当一个定时器被已经被插入内核动态定时器链表,我们可以通过这个函数来修改他的的expires; 需要注意的是,这个定时器函数是被一个类似硬件中断(软中断)所触发,所以它处在中断上下文(原子上下文)中而不是进程上下文。当你处在进程上下文之外,你必须遵守下列规则: 1)没有允许存取用户空间. 因为没有进程上下文, 没有和任何特定进程相关联的到用户空间的途径.2)这个 current 指针在原子态没有意义, 并且不能使用因为相关的代码没有和已被中断的进程的联系.3)不能进行睡眠或者调度. 原子代码不能调用 schedule 或者某种 wait_event, 也不能调用任何其他可能睡眠的函数. 例如, 调用 kmalloc(..., GFP_KERNEL) 是违犯规则的. 旗标也必须不能使用因为它们可能睡眠。 例程: #include #include #include #define TIMER_INTERVAL (5 * HZ) //5sstatic struct timer_list timer;static long unsigned int start;static voidhello_cleanup(void){ del_timer_sync(&timer);}voidtimer_function(unsigned long arg){ long unsigned int current_time = jiffies; printk(KERN_INFO "timer:%d\n", (int)((current_time - start) / HZ)); mod_timer((struct timer_list*)arg, current_time + TIMER_INTERVAL);}static __init int hello_init(void){ start = jiffies; init_timer(&timer); timer.expires = start + TIMER_INTERVAL; timer.function = timer_function; timer.data = (unsigned long)&timer; add_timer(&timer); printk(KERN_ALERT "hello init success!\n"); return 0;}static __exit void hello_exit(void){ hello_cleanup(); printk(KERN_WARNING "helloworld exit!\n");}module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Stone"); |
CopyRight 2018-2019 实验室设备网 版权所有 |