Linux定时器
目录
在Linux设备驱动编程中, 可以利用Linux内核中提供的一组函数和数据结构来完成定时触发工作或者完成某周期性的事务。
软件意义上的定时器最终依赖硬件定时器来实现
内核在时钟中断发生后检测各定时器是否到期, 到期后的定时器处理函数将作为软中断在底半部执行。
timer_list结构体:
struct timer_list {
/*
* All fields that change during normal runtime grouped to the
* same cacheline
*/
struct list_head entry;
unsigned long expires;
struct tvec_base *base;
void (*function)(unsigned long);
unsigned long data;
int slack;
#ifdef CONFIG_TIMER_STATS
int start_pid;
void *start_site;
char start_comm[16];
#endif
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
当定时器期满后,其中第10行的function() 成员将被执行, 而第11行的data成员则是传入其中的参数, 第7行的expires则是定时器到期的时间(jiffies)
使用:
初始化定时器以及初始化绑定参数
//初始化timer_list的entry的next为NULL, 并给base指针赋值。
struct timer_list my_timer;
//赋值定时器结构体的function、 expires、data和base成员
TIMER_INITIALIZER(_function, _expires, _data)
//等价于
#define TIMER_INITIALIZER(_function, _expires, _data) {
.entry = { .prev = TIMER_ENTRY_STATIC },
.function = (_function),
.expires = (_expires),
.data = (_data), \
.base = &boot_tvec_bases,
}
//定义并初始化定时器成员的“快捷方式”
DEFINE_TIMER(_name, _function, _expires, _data)
//等价于
#define DEFINE_TIMER(_name, _function, _expires, _data)
struct timer_list _name =TIMER_INITIALIZER(_function, _expires, _data)
//setup_timer() 也可用于初始化定时器并赋值其成员
#define __setup_timer(_timer, _fn, _data, _flags)
do {
__init_timer((_timer), (_flags));
(_timer)->function = (_fn);
(_timer)->data = (_data);
} while (0)
增加定时器
上述函数用于注册内核定时器, 将定时器加入到内核动态定时器链表中。
void add_timer(struct timer_list * timer);
删除定时器
del_timer_sync() 是del_timer() 的同步版, 在删除一个定时器时需等待其被处理完, 因此该函数的调用不能发生在中断上下文中
int del_timer(struct timer_list * timer)
修改定时器
上述函数用于修改定时器的到期时间, 在新的被传入的expires到来后才会执行定时器函数。
int mod_timer(struct timer_list *timer, unsigned long expires);
延迟工作(delayed work)
对于周期性任务,除了可以使用定时器以外, 在Linux内核中还可以利用一套封装得很好的快捷机制, 其本质是利用工作队列和定时器实现, 这套快捷机制就是delayed_work
struct delayed_work {
struct work_struct work;
struct timer_list timer;
/* target workqueue and CPU ->timer uses to queue ->work */
struct workqueue_struct *wq;
int cpu;
};
内核延时
短延迟
void ndelay(unsigned long nsecs);//纳秒
void udelay(unsigned long usecs);//微秒
void mdelay(unsigned long msecs);//毫秒
长延迟
本质是忙等待,通过使用time_before() 和time_after()对目前的jiffies以及目标jiffies进行比较,从而达到延时效果
/* 延迟100个jiffies */
unsigned long delay = jiffies + 100;
while(time_before(jiffies, delay));
/* 再延迟2s */
unsigned long delay = jiffies + 2*Hz;
while(time_before(jiffies, delay));
睡着延迟
睡着延迟是指在等待时间到来之前,使进程处于睡眠状态,CPU的资源会被其他的进程使用。
schedule_timeout()
//使当前任务休眠至指定的jiffies之后再重新被调度执行
//实现原理是向系统添加一个定时器, 在定时器处理函数中唤醒与参数对应的进程
posted on 2022-08-13 16:15 DylanYeung 阅读(354) 评论(0) 编辑 收藏 举报