Linux内核驱动之延时---内核超时处理【转】
這個計數器和來讀取它的實用函數位于?,?盡管你會常常只是包含?,
#include unsigned long j, stamp_1, stamp_half, stamp_n; j = jiffies; /* read the current value */ stamp_1 = j + HZ; /* 1 second in the future */ stamp_half = j + HZ/2; /* half a second */ stamp_n = j + n * HZ / 1000; /* n milliseconds */?
忙等待如果你想延時執行多個時鐘嘀噠,?允許在值中某些疏忽,?最容易的(?盡管不推薦?)?的實現是一個監視?jiffy?計數器的循環.?這種忙等待實現常常看來象下面的代碼,?這里?j1?是?jiffies?的在延時超時的值:
while (time_before(jiffies, j1)){}
超時 到目前為止所展示的次優化的延時循環通過查看?jiffy?計數器而不告訴任何人來工作.?但是最好的實現一個延時的方法,?如你可能猜想的,?常常是請求內核為你做.?有?2?種方法來建立一個基于?jiffy?的超時,?依賴于是否你的驅動在等待其他的事件.如果你的驅動使用一個等待隊列來等待某些其他事件,?但是你也想確保它在一個確定時間段內運行,?可以使用?wait_event_timeout?或者wait_event_interruptible_timeout:
#include long wait_event_timeout(wait_queue_head_t q, condition, long timeout); long wait_event_interruptible_timeout(wait_queue_head_t q, condition, long timeout);這些函數在給定隊列上睡眠,?但是它們在超時(以?jiffies?表示)到后返回.?因此,?它們實現一個限定的睡眠不會一直睡下去.?注意超時值表示要等待的jiffies?數,?不是一個絕對時間值.?這個值由一個有符號的數表示,?因為它有時是一個相減運算的結果,?盡管這些函數如果提供的超時值是負值通過一個printk?語句抱怨.?如果超時到,?這些函數返回?0;?如果這個進程被其他事件喚醒,?它返回以?jiffies?表示的剩余超時值.?返回值從不會是負值,?甚至如果延時由于系統負載而比期望的值大.
wait_event_timeout?和?wait_event_interruptible_timeout?被設計為有硬件驅動存在,?這里可以用任何一種方法來恢復執行:?或者有人調用?wake_up?在等待隊列上,?或者超時到.?這不適用于?jitqueue,?因為沒人在等待隊列上調用?wake_up (?畢竟,?沒有其他代碼知道它?),?因此這個進程當超時到時一直喚醒.?為適應這個特別的情況,?這里你想延后執行不等待特定事件,?內核提供了?schedule_timeout?函數,?因此你可以避免聲明和使用一個多余的等待隊列頭:
#include signed long schedule_timeout(signed long timeout);這里, timeout?是要延時的?jiffies?數.?返回值是?0?除非這個函數在給定的?timeout?流失前返回(響應一個信號). schedule_timeout?請求調用者首先設置當前的進程狀態,?因此一個典型調用看來如此:
set_current_state(TASK_INTERRUPTIBLE); schedule_timeout (delay);第一行調用?set_current_state?來設定一些東西以便調度器不會再次運行當前進程,?直到超時將它置回?TASK_RUNNING?狀態.?為獲得一個不可中斷的延時,?使用?TASK_UNINTERRUPTIBLE?代替.
短延時
當一個設備驅動需要處理它的硬件的反應時間,?涉及到的延時常常是最多幾個毫秒.
內核函數?ndelay, udelay,?以及?mdelay?對于短延時好用,?分別延后執行指定的納秒數,?微秒數或者毫秒數.?它們的原型是:
#include void ndelay(unsigned long nsecs); void udelay(unsigned long usecs); void mdelay(unsigned long msecs);有另一個方法獲得毫秒(和更長)延時而不用涉及到忙等待.?文件?聲明這些函數:
void msleep(unsigned int millisecs); unsigned long msleep_interruptible(unsigned int millisecs); void ssleep(unsigned int seconds)前?2?個函數使調用進程進入睡眠給定的毫秒數.?一個對?msleep?的調用是不可中斷的;?你能確保進程睡眠至少給定的毫秒數.?如果你的驅動位于一個等待隊列并且你想喚醒來打斷睡眠,?使用?msleep_interruptible.?從?msleep_interruptible?的返回值正常地是?0;?如果,?但是,?這個進程被提早喚醒,?返回值是在初始請求睡眠周期中剩余的毫秒數.?對?ssleep?的調用使進程進入一個不可中斷的睡眠給定的秒數.
【作者】張昺華 【出處】http://www.cnblogs.com/sky-heaven/ 【博客園】 http://www.cnblogs.com/sky-heaven/ 【新浪博客】 http://blog.sina.com.cn/u/2049150530 【知乎】 http://www.zhihu.com/people/zhang-bing-hua 【我的作品---旋轉倒立擺】 http://v.youku.com/v_show/id_XODM5NDAzNjQw.html?spm=a2hzp.8253869.0.0&from=y1.7-2 【我的作品---自平衡自動循跡車】 http://v.youku.com/v_show/id_XODM5MzYyNTIw.html?spm=a2hzp.8253869.0.0&from=y1.7-2 【新浪微博】 張昺華--sky 【twitter】 @sky2030_ 【facebook】 張昺華 zhangbinghua 本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利. 與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Linux内核驱动之延时---内核超时处理【转】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 由浅到深讲解C#-LINQ
- 下一篇: 追求代码质量: 用 AOP 进行防御性编