内核定时器与延时

内核需要定时器来实现一定的延时。

       数据结构定义:

struct timer_list {

struct list_head entry; /* entry in linked list of timers */

unsigned long expires; /* expiration value, in jiffies */

void (*function)(unsigned long); /* the timer handler function */

unsigned long data; /* lone argument to the handler */

struct tvec_t_base_s *base; /* internal timer field, do not touch */

};

       操作:

void init_timer(struct timer_list *timer);

TIMER_INITIALIZER(_functioin, _expires, _data)宏用于赋值定时器结构体的functionexpiresdatabase成员。

DEFINE_TIMER(_name, _function, _expires, _data)

setup_timer()也可用于初始化定时器并赋值其成员。

增加定时器

void add_timer(struct timer_list *timer);

删除定时器

int del_timer(struct timer_list *timer);

int del_timer _sync (struct timer_list *timer);注:该函数不能用于中断上下文中,其他情况下尽量用户该函数。

修改定时器的expire

 int mod_timer(struct timer_list *timer, unsigned long expires);

内核定时器模板

/*XXX设备结构体*/

struct xxx_dev

{

struct cdev cdev;

timer_list xxx_timer;/*设备要使用的定时器*/

};

 

/*xxx驱动中的某函数*/

xxx_funcl(…)

{

struct xxx_dev *dev = filp->private_data;

/*初始化定时器*/

init_timer(&dev->xxx_timer);

dev->xxx_timer.function = &xxx_do_timer;

dev->xxx_timer.data = (unsigned long)dev;

/*设备结构体指针作为定时器处理函数参数*/

dev->xxx_timer.expires = jiffies + delay;

/*添加(注册)定时器*/

add_timer(&dev->xxx_timer);

};

 

/*xxx驱动中的某函数*/

xxx_func2(…)

{

/*删除定时器*/

del_timer(&dev->xxx_timer);

}

 

/*定时器处理函数*/

static void xxx_do_timer(unsigned long arg)

{

     struct xxx_device *dev = (struct xxx_device*)(arg);

     …

     /*调度定时器再执行*/

     dev->xxx_timer.expires = jiffies + delay;

     add_timer(&dev->xxx_timer);

     …

}

 

延时机制

1. 忙等待,如:

unsigned long timeout = jiffies + 10; /* ten ticks */

while (time_before(jiffies, timeout))

;

2. 重新调度,如:

unsigned long delay = jiffies + 5*HZ;

while (time_before(jiffies, delay))

cond_resched();

其中,cond_resched()仅调度一个设置了need_resched标志的进程。

3. 小延时

       有时,内核代码需要更精确的延时,如小于一个时钟滴答。通常小于1毫秒,基于jiffies的延时是不能满足要求的。内核提供了三个函数分别处理微秒,纳秒和毫秒,原型如下:

void udelay(unsigned long usecs) //微秒

void ndelay(unsigned long nsecs) //纳秒

void mdelay(unsigned long msecs) //毫秒

udelay()实现为一个循环,它能知道一个给定的时间段有多少次迭代。mdelay()函数基于udelay()函数实现的。内核知道处理器1秒钟能完成的循环次数。udelay()函数仅用于非常小的延迟。超过1毫秒的延迟不要使用udelay()。对于较长的延时,使用mdelay()。类似于忙等待,一般情况下,不要使用这些函数,除非有必要。

4. schedule_timeout()

     一种更好的延迟执行的方式是使用schedule_timeout()函数。该调用将当前任务标记为睡眠状态直到指定的时间已经过去。通常,睡眠的时间很难保证与指定指定的时间一致。调用方式如下:

/* set task’s state to interruptible sleep */

set_current_state(TASK_INTERRUPTIBLE);

/* take a nap and wake up in “s” seconds */

schedule_timeout(s * HZ);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值