在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應用 > linux驅(qū)動之內(nèi)核定時器驅(qū)動設(shè)計

            linux驅(qū)動之內(nèi)核定時器驅(qū)動設(shè)計

            作者: 時間:2016-12-01 來源:網(wǎng)絡 收藏
            我的環(huán)境:
            Fedora 14 內(nèi)核版本為2.6.38.1
            開發(fā)板:ARM9 TQ2440
            移植內(nèi)核版本:linux-2.6.30.4
            定時器在linux內(nèi)核中主要是采用一個結(jié)構(gòu)體實現(xiàn)的。但是需要注意定時器是一個只運行一次的對象,也就是當一個定時器結(jié)束以后,還需要重現(xiàn)添加定時器。但是可以采用mod_timer()函數(shù)動態(tài)的改變定時器到達時間。
            這個驅(qū)動主要實現(xiàn)內(nèi)核定時器的基本操作。內(nèi)核定時器主要是是通過下面的結(jié)構(gòu)體struct timer_list實現(xiàn)。需要的頭文件包括#include,但是在實際開發(fā)過程中不需要包含該頭文件,因為在sched.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
            };
            定時器的實現(xiàn)主要是該結(jié)構(gòu)體的填充和部分函數(shù)的配合即可完成。其中紅色的部分是最主要的幾個元素,1、expires主要是用來定義定時器到期的時間,通常采用jiffies這個全局變量和HZ這個全局變量配合設(shè)置該元素的值。比如expires = jiffies + n*HZ,其中jiffies是自啟動以來的滴答數(shù),HZ是一秒種的滴答數(shù)。
            2、function可以知道是一個函數(shù)指針,該函數(shù)就是定時器的處理函數(shù),類似我們在中斷中的中斷函數(shù),其實定時器和中斷有很大的相似性。定時器處理函數(shù)是自己定義的函數(shù)。
            3、data通常是實現(xiàn)參數(shù)的傳遞,從function的參數(shù)類型可以知道,data可以作為定時器處理函數(shù)的參數(shù)。
            其他的元素可以通過內(nèi)核的函數(shù)來初始化。
            初始化函數(shù)為:
            init_timer(struct timer_list * timer);
            或者直接DEFINE_TIMER宏實現(xiàn)定義和初始化操作。
            #define DEFINE_TIMER(_name, _function, _expires, _data)
            struct timer_list _name =
            TIMER_INITIALIZER(_function, _expires, _data)
            添加定時器到內(nèi)核的函數(shù):
            void add_timer(struct timer_list *timer)
            {
            BUG_ON(timer_pending(timer));
            mod_timer(timer, timer->expires);
            }
            刪除定時器函數(shù),如果定時器的定時時間還沒有到達,那么才可以刪除定時器:
            int del_timer(struct timer_list *timer)
            修改定時器的到達時間,該函數(shù)的特點是,不管定時器是否到達時間,都會重現(xiàn)添加一個定時器到內(nèi)核。所以可以在定時處理函數(shù)中可以調(diào)用該函數(shù)修改需要重新定義的到達時間。
            int mode_timer(struct timer_list *timer,unsigned long expires)
            int mod_timer(struct timer_list *timer, unsigned long expires)
            {
            /*
            * This is a common optimization triggered by the
            * networking code - if the timer is re-modified
            * to be the same thing then just return:
            */
            if (timer->expires == expires && timer_pending(timer))
            return 1;
            /*注意調(diào)用的條件,也就是說明當前的定時器為鏈表的最后一個*/
            return __mod_timer(timer, expires, false);
            }
            static inline int
            __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
            {
            struct tvec_base *base, *new_base;
            unsigned long flags;
            int ret;
            ret = 0;
            timer_stats_timer_set_start_info(timer);
            BUG_ON(!timer->function);
            base = lock_timer_base(timer, &flags);
            if (timer_pending(timer)) {
            detach_timer(timer, 0);
            ret = 1;
            } else {
            if (pending_only)
            goto out_unlock;
            }
            debug_timer_activate(timer);
            new_base = __get_cpu_var(tvec_bases);
            if (base != new_base) {
            /*
            * We are trying to schedule the timer on the local CPU.
            * However we cant change timers base while it is running,
            * otherwise del_timer_sync() cant detect that the timers
            * handler yet has not finished. This also guarantees that
            * the timer is serialized wrt itself.
            */
            if (likely(base->running_timer != timer)) {
            /* See the comment in lock_timer_base() */
            timer_set_base(timer, NULL);
            spin_unlock(&base->lock);
            base = new_base;
            spin_lock(&base->lock);
            timer_set_base(timer, base);
            }
            }
            timer->expires = expires;
            internal_add_timer(base, timer);
            out_unlock:
            spin_unlock_irqrestore(&base->lock, flags);
            return ret;
            }
            static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
            {
            unsigned long expires = timer->expires;
            unsigned long idx = expires - base->timer_jiffies;
            struct list_head *vec;
            if (idx < TVR_SIZE) {
            int i = expires & TVR_MASK;
            vec = base->tv1.vec + i;
            } else if (idx < 1 << (TVR_BITS + TVN_BITS)) {
            int i = (expires >> TVR_BITS) & TVN_MASK;
            vec = base->tv2.vec + i;
            } else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) {
            int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK;
            vec = base->tv3.vec + i;
            } else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) {
            int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK;
            vec = base->tv4.vec + i;
            } else if ((signed long) idx < 0) {
            /*
            * Can happen if you add a timer with expires == jiffies,
            * or you set a timer to go off in the past
            */
            vec = base->tv1.vec + (base->timer_jiffies & TVR_MASK);
            } else {
            int i;
            /* If the timeout is larger than 0xffffffff on 64-bit
            * architectures then we use the maximum timeout:
            */
            if (idx > 0xffffffffUL) {
            idx = 0xffffffffUL;
            expires = idx + base->timer_jiffies;
            }
            i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK;
            vec = base->tv5.vec + i;
            }
            /*
            * Timers are FIFO:
            */
            /*添加到鏈表的最后,這說明mod_timer實現(xiàn)了重新注冊一個定時器的操作*/
            list_add_tail(&timer->entry, vec);
            }
            從上面的分析可以看出,mod_timer的實現(xiàn)過程比較復雜,但是基本上說明了mod_timer函數(shù)重新注冊定時器的操作過程。
            一般而言定時器的基本操作主要是上面的幾個函數(shù)。
            我的基于內(nèi)核定時器的驅(qū)動函數(shù)如下,參考了宋寶華的Linux設(shè)備驅(qū)動開發(fā)詳解(第二版)。
            上一頁 1 2 下一頁

            評論


            技術(shù)專區(qū)

            關(guān)閉