<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

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

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

          作者: 時間:2016-12-01 來源:網(wǎng)絡(luò) 收藏
          我的環(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)過程比較復(fù)雜,但是基本上說明了mod_timer函數(shù)重新注冊定時器的操作過程。
          一般而言定時器的基本操作主要是上面的幾個函數(shù)。
          我的基于內(nèi)核定時器的驅(qū)動函數(shù)如下,參考了宋寶華的Linux設(shè)備驅(qū)動開發(fā)詳解(第二版)。
          上一頁 1 2 下一頁

          評論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();