驅動開發之始,(六)Linux核心時間,延遲操作

2021-10-04 19:24:32 字數 2549 閱讀 2509

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的驅動框架有很多 字元裝置驅動框架 塊裝置驅動...