1. 程式人生 > >Linux kernel 核心延時函式

Linux kernel 核心延時函式

其他參考:http://blog.csdn.net/lixiaojie1012/article/details/44229009

當一個裝置驅動需要處理它的硬體的反應時間, 涉及到的延時常常是最多幾個毫秒. 在這個情況下, 依靠時鐘嘀噠顯然不對路.

The kernel functions ndelay, udelay, and mdelay serve well for short delays, delaying execution for the specified number of nanoseconds, microseconds, or milliseconds respectively.* Their prototypes are: * The u in udelay represents the Greek letter mu and stands for micro.

核心函式 ndelay, udelay, 以及 mdelay 對於短延時好用, 分別延後執行指定的納秒數, 微秒數或者毫秒數. [27]它們的原型是:

#include <linux/delay.h>
void ndelay(unsigned long nsecs);
void udelay(unsigned long usecs);
void mdelay(unsigned long msecs);

這些函式的實際實現在 <asm/delay.h>, 是體系特定的, 並且有時建立在一個外部函式上. 每個體系都實現 udelay, 但是其他的函式可能或者不可能定義; 如果它們沒有定義, <

Linux/delay.h> 提供一個預設的基於 udelay 的版本. 在所有的情況中, 獲得的延時至少是要求的值, 但可能更多; 實際上, 當前沒有平臺獲得了納秒的精度, 儘管有幾個提供了次微秒的精度. 延時多於要求的值通常不是問題, 因為驅動中的短延時常常需要等待硬體, 並且這個要求是等待至少一個給定的時間流失.

udelay 的實現( 可能 ndelay 也是) 使用一個軟體迴圈基於在啟動時計算的處理器速度, 使用整數變數 loos_per_jiffy. 如果你想看看實際的程式碼, 但是, 小心 x86 實現是相當複雜的一個因為它使用的不同的時間源, 基於什麼 CPU 型別在執行程式碼.

為避免在迴圈計算中整數溢位, udelay 和 ndelay 強加一個上限給傳遞給它們的值. 如果你的模組無法載入和顯示一個未解決的符號, __bad_udelay, 這意味著你使用太大的引數呼叫 udleay. 注意, 但是, 編譯時檢查只對常量進行並且不是所有的平臺實現它. 作為一個通用的規則, 如果你試圖延時幾千納秒, 你應當使用 udelay 而不是 ndelay; 類似地, 毫秒規模的延時應當使用 mdelay 完成而不是一個更細粒度的函式.

重要的是記住這 3 個延時函式是忙等待; 其他任務在時間流失時不能執行. 因此, 它們重複, 儘管在一個不同的規模上, jitbusy 的做法. 因此, 這些函式應當只用在沒有實用的替代時.

有另一個方法獲得毫秒(和更長)延時而不用涉及到忙等待. 檔案 <linux/delay.h> 宣告這些函式:

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 的呼叫使程序進入一個不可中斷的睡眠給定的秒數.

通常, 如果你能夠容忍比請求的更長的延時, 你應當使用 schedule_timeout, msleep, 或者 ssleep.