zoukankan      html  css  js  c++  java
  • 内核定时器和延迟

    1. 定时器

    #include <timer.h>
    
    struct timer_list {
        struct list_head entry;
        unsigned long expires;
    
        void (*function)(unsigned long);
        unsigned long data;
    
        struct tvec_base *base;
    #ifdef CONFIG_TIMER_STATS
        void *start_site;
        char start_comm[16];
        int start_pid;
    #endif
    #ifdef CONFIG_LOCKDEP
        struct lockdep_map lockdep_map;
    #endif
    };
    static void timer_handle(unsigned long data)
    {
        mod_timer(&timer, jiffies + HZ);
    }
    
    struct timer_list timer;
    init_timer(&timer);
    timer.expires = expire;
    timer.data = (unsigned long )data;
    timer.function = timer_handle;
    add_timer(&timer);
    
    del_timer(&timer);

    HZ:每秒的周期次数(周期/秒)

    2. delay
    有时驱动程序不但需要很短暂的延迟(比时钟节拍还短)而且还要求延迟的时间很精确

    #include <delay.h>
    
    void ndelay(unsigned long nsecs)
    static inline void udelay(unsigned long usecs);
    #define mdelay(n) udelay((n) * 1000)

    毫秒级以上的延时,最好不要直接使用mdelay函数,这将无谓的浪费cpu的资源
    注:不要在持有锁时或禁止中断时使用忙等待

    3. sleep
    毫秒级以上的延时

    static inline void msleep(unsigned int msecs)
    {
        unsigned long timeout = MSECS(msecs) + 1;
    
        while (timeout) {
            set_current_state(TASK_UNINTERRUPTIBLE);
            timeout = schedule_timeout(timeout);
        }
    }
    
    unsigned long msleep_interruptible(unsigned int msecs)
    {
        unsigned long timeout = msecs_to_jiffies(msecs) + 1;
    
        while (timeout && !signal_pending(current))
            timeout = schedule_timeout_interruptible(timeout);
        return jiffies_to_msecs(timeout);
    }
    
    static inline void ssleep(unsigned int seconds)
    {
        msleep(seconds * 1000);
    }

    注:受系统HZ以及进程调度的影响,msleep类似函数的精度是有限的

    4. 长延迟

    #define time_after(a,b)     
        (typecheck(unsigned long, a) && 
         typecheck(unsigned long, b) && 
         ((long)(b) - (long)(a) < 0))
    #define time_before(a,b)    time_after(b,a)

    5. schedule_timeout
    让需要延迟执行的任务睡眠到指定的延迟时间耗尽后再重新运行

    //睡s秒后自动唤醒
    schedule_timeout(s * HZ);

    由于schedule_timeout函数需要调用调度程序,所以调用它的代码必须保证能够睡眠,调用代码必须处于进程上下文中,并且不能持有锁

    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
    ", timeout);
                dump_stack();
                current->state = TASK_RUNNING;
                goto out;
            }
        }
    
        expire = timeout + jiffies;
    
        setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);
        __mod_timer(&timer, expire, false, TIMER_NOT_PINNED);
        schedule();
        del_singleshot_timer_sync(&timer);
    
        /* Remove the timer from the object tracker */
        destroy_timer_on_stack(&timer);
    
        timeout = expire - jiffies;
    
     out:
        return timeout < 0 ? 0 : timeout;
    }
    signed long __sched schedule_timeout_interruptible(signed long timeout)
    {
        __set_current_state(TASK_INTERRUPTIBLE);
        return schedule_timeout(timeout);
    }
  • 相关阅读:
    20162302
    20162302
    20162302 实验三《敏捷开发与XP实践》实验报告
    20162302 第九周作业
    20162302 第八周作业
    20162302 实验二《面向对象程序设计》实验报告
    20162302 第七周作业
    项目Alpha冲刺Day8
    项目Alpha冲刺Day7
    项目Alpha冲刺Day5
  • 原文地址:https://www.cnblogs.com/zhangxuechao/p/11709803.html
Copyright © 2011-2022 走看看