1.使用jiffies計數器
該計數器和讀取計數器的工具函式包含在中,通常只需包含後自動加入jiffies.h
unsigned long volatile __jiffy_data jiffies
該變數被宣告為volatile,這樣可避免編譯器對訪問該變數的語句優化。在**需要計算未來的時間戳時,必須讀取當前的計數器。
有時需要將來自使用者空間的時間表示方法(使用struct timeval和struct timespec)和核心表述方法進行轉換。這兩個結構體使用兩個數來表示精確的時間
struct timespec ;
struct timeval ;
核心提供一下四個函式,完成jiffies值和這些結構間的轉換
unsigned long timespec_to_jiffies(const struct timespec *value);
void jiffies_to_timespec(const unsigned long jiffies, struct timespec *value);
unsigned long timeval_to_jiffies(const struct timeval *value);
void jiffies_to_timeval(const unsigned long jiffies, struct timeval *value);
對於64位的jiffies_64的訪問不像對jiffies那樣直接。在64為計算機結構上,兩個變數是同乙個,但在32位處理器上就靠不住了,因為在讀取高 32位和低32位時,可能會發生更新,從而獲得錯誤的值。因此,讀取jiffies_64時應該使用核心匯出函式
u64 get_jiffies_64(void)
2.獲取當前時間
核心一般通過jiffies值來獲取當前時間。該數值表示的是自最近一次系統啟動到當前的時間間隔,它和裝置驅動程式無關,因為它的生命週期只限於系統的執行期間(uptime)。但驅動程式可以利用jiffies的當前值來計算不同事件間的時間間隔,例如輸入裝置驅動程式就用它來分辨滑鼠的單雙擊。
核心提供了將牆鐘時間轉換為jiffies值的函式
unsigned long mktime(const unsigned int year, const unsigned int mon,
const unsigned int day, const unsigned int hour,
const unsigned int min, const unsigned int sec);
雖然核心空間不必處理人類表達的時間,但有時也需要處理絕對時間間隔。
3.延遲執行
裝置驅動程式經常需要將某些特定**延遲一段時間後執行——通常是為了讓硬體能完成某些任務。
把涉及多個時鐘滴答的延遲稱為「長延遲」。重點講一下超時
通過監視jiffies計數器實現的延遲迴圈可以工作,但不是非常理想。實現延遲的最好方法應該是讓核心為我們完成相應的工作,存在兩種構造基於jiffies超時的途徑,使用哪個則依賴於驅動程式是否在等待其他事件。如果驅動程式使用等待佇列來等待其他一些事件,而我們同時希望在特定的時間段中執行,則可以使用wait_event_timeout和wait_event_interruptible_timeout巨集
#define wait_event_timeout(wq, condition, timeout)
#define wait_event_interruptible_timeout(wq, condition, timeout)
上述函式會在給定的等待佇列上休眠,但是會在超時(用jiffies表示)到期時返回。
當裝置驅動需要處理硬體的延遲(latency)時,最多涉及幾十個毫秒,這種情況下,依賴時鐘滴答顯然不行。在中核心指定了幾個完成短任務的函式,mdelay、udelay和ndelay分別指定毫秒、微妙和納秒
void mdelay(unsigned long msecc)
void udelay(unsigned long usecs);
void ndelay(unsigned long nsecs);
注意,上面這三個延遲函式均是忙等函式,因而在延遲過程中無法執行其他任何任務。
還有另外一種不涉及忙等待,實現延遲的方法
void msleep(unsigned int msecs);
unsigned long msleep_interruptible(unsigned int msecs);
以上兩個呼叫程序休眠以給定的msecs,對msleep的呼叫是不可中斷的;如果驅動程式正在某個等待佇列上等待,而又希望有喚醒能夠打斷這個等待的話,可使用msleep_interruptible
void ssleep(unsigned int seconds);
ssleep呼叫使程序進入不可中斷的休眠,以秒計數。 Linux 核心 驅動開發總結
總體來看,需要乙個階段性總結了,因為現在sd卡的除錯也進入了卡殼期。大概會出一系列的總結文章,主要涉及的主題在下面列出 1 開發工具 gcc gdb vim ctags 2 makefile和kconfig linux核心的配置與編譯,更好的理解模組化開發 3 除錯技術 無敵的printf等 注意整...
Linux裝置驅動 核心開發
linux裝置驅動需要使用核心api來實現,一般被包含在linux核心原始碼樹中。驅動可以編譯到核心,隨著核心一起在系統啟動的時候被載入。也可以編譯成核心模組,在系統執行起來之後動態地載入到核心中,使得除錯的時候無需重新編譯核心,也無需重啟系統,很大程度上方便了驅動 的除錯。但並不是只有裝置驅動才能...
linux核心字元裝置驅動開發
1,對驅動的理解 對於一般驅動程式來說,只需要配置控制器的暫存器就可以 但是在linux作業系統中,軟體要讓硬體辦事,就要滿足硬體的規矩,也就是按驅動框架來開發硬體驅動程式 驅動程式就要受到linux的約束,這個約束就被稱為linux驅動框架。linux的驅動框架有很多 字元裝置驅動框架 塊裝置驅動...