亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Linux內核定時器與延遲工作怎么實現

發布時間:2021-12-24 14:05:30 來源:億速云 閱讀:226 作者:iii 欄目:系統運維

本篇內容介紹了“Linux內核定時器與延遲工作怎么實現”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

內核定時器

軟件上的定時器最終要依靠硬件時鐘來實現,簡單的說,內核會在時鐘中斷發生后檢測各個注冊到內核的定時器是否到期,如果到期,就回調相應的注冊函數,將其作為中斷底半部來執行。實際上,時鐘中斷處理程序會觸發TIMER_SOFTIRQ軟中斷,運行當前處理器上到期的所有定時器。

設備驅動程序如要獲得時間信息以及需要定時服務,都可以使用內核定時器。

jiffies

要說內核定時器,首先就得說說內核中關于時間的一個重要的概念:jiffies變量,作為內核時鐘的基礎,jiffies每隔一個固定的時間就會增加1,稱為增加一個節拍,這個固定間隔由定時器中斷來實現,每秒中產生多少個定時器中斷,由在<linux/param.h>中定義的HZ宏來確定,如此,可以通過jiffies獲取一段時間,比如jiffies/HZ表示自系統啟動的秒數。下兩秒就是(jiffies/HZ+2),內核中用jiffies來計時,秒轉換成的jiffies:seconds*HZ,所以以jiffiy為單位,以當前時刻為基準計時2秒:(jiffies/HZ+2)*HZ=jiffies+2*HZ如果要獲取當前時間,可以使用do_gettimeofday(),該函數填充一個struct timeval結構,有著接近微妙的分辨率。

//kernel/time/timekeeping.c /** * do_gettimeofday - Returns the time of day in a timeval * @tv:         pointer to the timeval to be set * * NOTE: Users should be converted to using getnstimeofday() */ void do_gettimeofday(struct timeval *tv)

驅動程序為了讓硬件有足夠的時間完成一些任務,常常需要將特定的代碼延后一段時間來執行,根據延時的長短,內核開發中使用長延時和短延時兩個概念。長延時的定義為:延時時間>多個jiffies,實現長延時可以用查詢jiffies的方法:

time_before(jiffies, new_jiffies); time_after(new_jiffiesmjiffies);

**短延時的定義為:延遲事件接近或短于一個jiffy,實現短延時可以調用

udelay(); mdelay();

這兩個函數都是忙等待函數,大量消耗CPU時間,前者使用軟件循環來延遲指定數目的微妙數,后者使用前者的嵌套來實現毫秒級的延時。

定時器

驅動可以注冊一個內核定時器,來指定一個函數在未來某個時間來執行。定時器從注冊到內核開始計時,達到指定的時間后會執行注冊的函數。即超時值是一個jiffies值,當jiffies值大于timer->expires時,timer->function就會被執行。API如下

//定一個定時器  struct timer_list my_timer;//初始化定時器  void init_timer(struct timer_list *timer); mytimer.function = my_function; mytimer.expires = jiffies +HZ;//增加定時器  void add_timer(struct timer_list *timer);//刪除定時器  int del_tiemr(struct timer_list *timer);

實例

static struct timer_list tm; struct timeval oldtv;void callback(unsigned long arg){     struct timeval tv;     char *strp = (char*)arg;     do_gettimeofday(&tv);     printk("%s: %ld, %ld\n", __func__,         tv.tv_sec - oldtv.tv_sec,         tv.tv_usec- oldtv.tv_usec);     oldtv = tv;     tm.expires = jiffies+1*HZ;     add_timer(&tm); } static int __init demo_init(void){     init_timer(&tm);     do_gettimeofday(&oldtv);     tm.function= callback;     tm.data    = (unsigned long)"hello world";     tm.expires = jiffies+1*HZ;     add_timer(&tm);     return 0; }

延遲工作

除了使用內核定時器完成定時延遲工作,Linux內核還提供了一套封裝好的"快捷方式"-delayed_work,和內核定時器類似,其本質也是利用工作隊列和定時器實現,

//include/linux/workqueue.h  struct work_struct {                     atomic_long_t data;          struct list_head entry;          work_func_t func;  #ifdef CONFIG_LOCKDEP          struct lockdep_map lockdep_map;  #endif  };  struct delayed_work {              114         struct work_struct work;          struct timer_list timer;    /* target workqueue and CPU ->timer uses to queue ->work */          struct workqueue_struct *wq;          int cpu;  };

--103-->需要延遲執行的函數, typedef void (work_func_t)(struct work_struct work);

至此,我們可以使用一個delayed_work對象以及相應的調度API實現對指定任務的延時執行

//注冊一個延遲執行  591 static inline bool schedule_delayed_work(struct delayed_work *dwork,unsigned long delay)//注銷一個延遲執行 2975 bool cancel_delayed_work(struct delayed_work *dwork)

和內核定時器一樣,延遲執行只會在超時的時候執行一次,如果要實現循環延遲,只需要在注冊的函數中再次注冊一個延遲執行函數。

schedule_delayed_work(&work,msecs_to_jiffies(poll_interval));

“Linux內核定時器與延遲工作怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

清徐县| 曲麻莱县| 合江县| 牙克石市| 綦江县| 民丰县| 疏勒县| 尖扎县| 漠河县| 寿光市| 中山市| 磐石市| 堆龙德庆县| 金溪县| 武义县| 永仁县| 大石桥市| 罗田县| 松原市| 金乡县| 礼泉县| 荃湾区| 双柏县| 镇坪县| 楚雄市| 阿图什市| 民勤县| 罗平县| 民权县| 彭泽县| 密山市| 大同市| 台北市| 正阳县| 耿马| 泸定县| 黄梅县| 深州市| 盐亭县| 枝江市| 哈密市|