久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

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

191次閱讀
沒有評論

共計 2959 個字符,預計需要花費 8 分鐘才能閱讀完成。

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

內核定時器

軟件上的定時器最終要依靠硬件時鐘來實現,簡單的說,內核會在時鐘中斷發生后檢測各個注冊到內核的定時器是否到期,如果到期,就回調相應的注冊函數,將其作為中斷底半部來執行。實際上,時鐘中斷處理程序會觸發 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 內核定時器與延遲工作怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注丸趣 TV 網站,丸趣 TV 小編將為大家輸出更多高質量的實用文章!

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-08-16發表,共計2959字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 长阳| 泽库县| 桦甸市| 鄂州市| 两当县| 洱源县| 乌恰县| 宁武县| 新源县| 乐业县| 太康县| 额敏县| 张家口市| 潞城市| 茌平县| 高唐县| 昭觉县| 万荣县| 如东县| 永善县| 新竹市| 任丘市| 牡丹江市| 江川县| 景泰县| 怀集县| 平南县| 遂平县| 甘南县| 曲周县| 平顺县| 九龙县| 德庆县| 宁安市| 淮安市| 南华县| 辉县市| 司法| 林周县| 扶沟县| 龙胜|