Chinaunix首页 | 论坛 | 博客
  • 博客访问: 244801
  • 博文数量: 63
  • 博客积分: 179
  • 博客等级: 入伍新兵
  • 技术积分: 342
  • 用 户 组: 普通用户
  • 注册时间: 2010-06-27 20:29
文章分类

全部博文(63)

文章存档

2019年(2)

2013年(5)

2012年(53)

2011年(3)

分类:

2012-06-11 20:48:13


  欢迎转载:http://kylinux.cublog.cn




定时器延迟

schedule_timeout()函数,会使需要延迟执行的任务睡眠到指定的延迟时间耗尽后再重新运行。

用法如下:
//将任务设置为可中断睡眠状态
set_current_state(TASK_INTERRUPTIBLE);

//小睡,“S”秒后醒
schedule_timeout(s*HZ)


fastcall signed long __sched schedule_timeout(signed long timeout)
{
        struct timer_list timer;
        unsigned long expire;

        switch (timeout)
        {
        case MAX_SCHEDULE_TIMEOUT:
                /*
                 * These two special cases are useful to be comfortable
                 * in the caller. Nothing more. We could take
                 * MAX_SCHEDULE_TIMEOUT from one of the negative value
                 * but I' d like to return a valid offset (>=0) to allow
                 * the caller to do everything it want with the retval.
                 */
                schedule();
                goto out;
        default:
                /*
                 * Another bit of PARANOID. Note that the retval will be
                 * 0 since no piece of kernel is supposed to do a check
                 * for a negative retval of schedule_timeout() (since it
                 * should never happens anyway). You just have the printk()
                 * that will tell you if something is gone wrong and where.
                 */
                if (timeout < 0) {
                        printk(KERN_ERR "schedule_timeout: wrong timeout "
                                "value %lx\n", timeout);
                        dump_stack();
                        current->state = TASK_RUNNING;
                        goto out;
                }
        }

        expire = timeout + jiffies;

        setup_timer(&timer, process_timeout, (unsigned long)current);
        __mod_timer(&timer, expire);
        schedule();
        del_singleshot_timer_sync(&timer);                                                                                                                   

        timeout = expire - jiffies;

 out:
        return timeout < 0 ? 0 : timeout;
}



函数 schedule_timeout 定义了一个软件时钟变量 timer ,在计算到期时间后初始化这个软件时钟:设置软件时钟当时间到期时的处理函数为 process_timeout ,参数为当前进程描述符,设置软件时钟的到期时间为 expire 。之后调用 schedule() 函数。此时当前进程睡眠,交出执行权,内核调用其它进程运行。但内核在每一个时钟中断处理结束后都要检测这个软件时钟是否到期。如果到期,将调用 process_timeout 函数,参数为睡眠的那个进程描述符。
其中MAX_SCHEDULE_TIMEOUT是用来检查任务是否无限期睡眠,如果是,函数不会为它设置定时器,这时调度会立即执行。




setup_timer()函数对定时器的初始化

static inline void setup_timer(struct timer_list * timer,

void (*function)(unsigned long),

unsigned long data)

{

timer->function = function;

timer->data = data;

init_timer(timer);

}
其中对base字段的赋值是调用了init_timer()函数。




process_timeout()函数
static void process_timeout(unsigned long __data)
{
    wake_up_process((struct task_struct *)__data);
}


函数 process_timeout 直接调用 wake_up_process 将进程唤醒。当内核重新调用该进程执行时,该进程继续执行 schedule_timeout 函数,执行流则从 schedule 函数中返回,之后调用 del_singleshot_timer_sync 函数将软件时钟卸载,然后函数 schedule_timeout 结束。


注:下章,做个总结。毕竟看了那么多,得总结下。看来我有个好习惯也,呵呵。

参考资料:
linux内核设计与实现
http://blog.ccidnet.com/blog-htm-do-showone-uid-84561-type-blog-itemid-258809.html
http://blog.chinaunix.net/u2/61477/showart_481379.html

http://hi.baidu.com/80695073/blog/item/9c170f55be0ae5c1b745ae5b.html
http://blog.chinaunix.net/u1/51562/showart_509400.html

http://www.ibm.com/developerworks/cn/linux/l-cn-clocks/index.html
阅读(988) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~