首页 > 代码库 > 定时器和时间管理

定时器和时间管理

一、jiffies    自系统启动以来产生的节拍的总数。

extern unsigned long volatile jiffies;
extern u64 jiffies_64;

比较时间的几个宏:
time_after(unknown, known)                    //unknown after known ? true : false;
time_before(unknown, known)                   //unknown before known ? true : false;
time_after_eq(unknown, known)                 //unknown after or eq known ? true : false;
time_before_eq(unknown, known)               //unknown before or eq known ? true : false;

其中unknown参数通常是jiffies,known参数是需要比对的值。

内核空间使用的节拍率:HZ
用户空间使用的节拍率:USER_HZ

jiffies_to_clock_t()                               //将一个由HZ表示的节拍计数转换成一个由USER_HZ表示的节拍计数
jiffies_64_to_clock_t()                            //将64位的jiffies值的单位从HZ转换为USER_HZ

二、定时器(动态定时器、内核定时器)
struct timer_list my_timer;

init_timer(&my_timer);        //初始化定时器数据结构的内部值

my_timer.expires = jiffies + delay;             //设置定时器超时时的节拍数
my_timer.data = http://www.mamicode.com/0;                              //设置定时器处理函数的参数
my_timer.function = my_function;                //设置定时器超时处理函数

定时器处理函数的函数原型:
void my_timer_function(unsigned long data);

add_timer(&my_timer);            //激活定时器

mod_timer(&my_timer, jiffies + new_dalay);        //改变指定定时器的超时时间
                                                  //如果定时器未被激活,mod_timer会激活该定时器
                                                  //如果调用时定时器未被激活,该函数返回0;否则返回1.
                                                                                            
del_timer(&my_timer);            //在定时器超时前停止定时器
                                 //被激活或未被激活的定时器都可以使用该函数
                                 //如果调用时定时器未被激活,该函数返回0;否则返回1.
                                 //不需要为已经超时的定时器调用该函数,因为他们会自动删除

del_timer_sync(&my_timer);    //等待可能在其他处理器上运行的定时器处理程序都退出后删除定时器。

注意:
del_timer_sync()函数不能在中断上下文中使用。

注意:禁止使用以下代码:
del_timer(&my_timer);
my_timer.expires = jiffies + new_delay;
add_timer(&my_timer);
代替函数:
mod_timer(&my_timer, jiffies + new_dalay);
否则在多处理器机器上是不安全的。

三、延迟执行

注意:延迟执行不管在哪种情况下,都不应该在持有锁时或禁止中断时发生。

1.忙等待

unsigned long timeout = jiffies + 10;

while(time_before(jiffies, timeout))
                    ;                     //延迟的时间是节拍的整数倍,精确率不高
                    
unsigned long delay = jiffies + 5 * HZ;
while(time_before(jiffies, delay))
    cond_resched();
                                //cond_resched()函数将调度一个新程序投入运行,但它只有在设置完need_resched标志后才能生效;
                                //也就是说,该方法有效的条件是系统中存在更重要的任务需要运行。
                                //它不能在中断上下文中使用,只能在进程上下文中使用。

2.短延迟

void udelay(unsigned long usecs)
void ndelay(unsigned long nsecs)
void mdelay(unsigned long msecs)

3.schedule_timeout()

set_current_state(state);        //将任务设置为可中断睡眠状态或不可中断睡眠状态
schedule_timeout(s*HZ);          //S秒后唤醒
                                 //当指定的时间到期后,内核唤醒被延迟的任务并将其重新放回运行队列。

注意:调用schedule_timeout()函数前必须首先将任务设置为上面两种状态之一,否则任务不会睡眠。
            调用代码必须处于进程上下文中,并且不能持有锁。
            
4.设置超时时间,在等待队列上睡眠。

使用条件:
    等待队列上的某个任务可能即在等待一个特定事件到来,又在等待一个特定时间到期——就看谁来的更快。

 

定时器和时间管理