05-Linux硬件定時 jiffies

本系列文章主要講Linux中的中斷和時間管理,文章機構如下:
01 - 驅動中的中斷處理
02 - 中斷下半部 tasklet
03 - 中斷的下半部 workqueue
04 - Linux中的延時操作函數
05 - Linux硬件定時 jiffies
06 - Linux 低分辨率定時器
07 - Linux高分辨率定時器

 本文內容參考正點原子《嵌入式 Linux驅動開發指南》一書,《嵌入式 Linux驅動開發指南》

1. 硬件時鐘源的介紹和配置

在Linux中硬件定時器提供時鐘源,時鐘源的可以在內核源碼目錄下,執行 make menuconfig 進行配置,配置界面如下圖所示:
在這裏插入圖片描述
 從上圖可以看出,硬件時鐘源一共可以選擇100Hz、250Hz、300Hz和1000Hz四種,配置完內核之後,可以在內核源碼目錄下的 .config 文件中看到已經將配置的時鐘頻率寫入到配置文件中,如下圖所示:
在這裏插入圖片描述
 除此之外,還可以在 include\asm-generic\param.h 文件中找到設置的時鐘頻率,如下所示:
在這裏插入圖片描述
 採用不同的時鐘頻率可以獲得不同的定時精度,高節拍率和低節拍率的優缺點如下:
 ①、高節拍率會提高系統時間精度,如果採用 100Hz 的節拍率,時間精度就是 10ms,採用1000Hz 的話時間精度就是 1ms,精度提高了 10 倍。高精度時鐘的好處有很多,對於那些對時間要求嚴格的函數來說,能夠以更高的精度運行,時間測量也更加準確。
②、高節拍率會帶導致中斷的產生更加頻繁,頻繁的中斷會加劇系統的負擔,1000Hz 的100Hz 的系統節拍率相比,系統要花費 10 倍的“精力”去處理中斷。中斷服務函數佔用處理器的時間增加,但是現在的處理器性能都很強大,所以採用 1000Hz 的系統節拍率並不會增加太大的負載壓力。根據自己的實際情況,選擇合適的系統節拍率,本教程我們全部採用默認的100Hz 系統節拍率。

2. jiffies

 Linux 內核使用全局變量 jiffies 來記錄系統從啓動以來的系統節拍數,系統啓動的時候會將 jiffies 初始化爲 0,jiffies 定義在文include/linux/jiffies.h 中,定義如下:

extern u64 __jiffy_data jiffies_64;						// 64位的jiffies_64
extern unsigned long volatile __jiffy_data jiffies;		// 32位的jiffies

 當我們訪問 jiffies 的時候其實訪問的是 jiffies_64 的低 32 位,使用 get_jiffies_64 這個函數可以獲取 jiffies_64 的值。在 32 位的系統上讀取 jiffies 的值,在 64 位的系統上 jiffes 和 jiffies_64表示同一個變量,因此也可以直接讀取 jiffies 的值。所以不管是 32 位的系統還是 64 位系統,都可以使用jiffies。前面說了 HZ 表示每秒的節拍數,jiffies 表示系統運行的 jiffies 節拍數,所以 jiffies/HZ 就是系統運行時間,單位爲秒。不管是 32 位還是 64 位的 jiffies,都有溢出的風險,溢出以後會重新從 0 開始計數,相當於繞回來了,因此有些資料也將這個現象也叫做繞回。假如 HZ 爲最大值 1000 的時候,32 位的 jiffies 只需要 4294967295(0xFFFFFFFF)/1000/3600/24 = 49.7 天就發生了繞回,對於 64 爲的 jiffies 來說大概需要5.8 億年才能繞回,因此 jiffies_64 的繞回忽略不計。處理 32 位 jiffies 的繞回顯得尤爲重要,

 Linux 內核提供了下面幾個 API 函數來對jiffies進行處理(include\linux\jiffies.h)

u64 get_jiffies_64(void)	// 獲取jiffies_64的值

time_after(a, b)			// a<b
time_before(a,b)			// a>b
time_after_eq(a,b)			// a<=b
time_before_eq(a,b)			// a>=b
time_in_range(a,b,c)		// b<=a<=c
time_in_range_open(a,b,c)	// b<=a<c

time_after64(a,b)			// a<b
time_before64(a,b)			// a>b
time_after_eq64(a,b)		// a<=b
time_before_eq64(a,b)		// a>=b
time_in_range64(a, b, c) 	// b<=a<=c

extern unsigned int jiffies_to_msecs(const unsigned long j)		// 將jiffies轉換爲對應的ms值
extern unsigned int jiffies_to_usecs(const unsigned long j)		// 將jiffies轉換爲對應的us值
static inline u64 jiffies_to_nsecs(const unsigned long j)		// 將jiffies轉換爲對應的ns值	
extern unsigned long __msecs_to_jiffies(const unsigned int m)	// 將ms轉換爲對應的jiffies值
extern unsigned long __usecs_to_jiffies(const unsigned int u)	// 將us轉換爲對應的jiffies值
extern unsigned long nsecs_to_jiffies(u64 n);					// 將ns轉換爲對應的jiffies值

 這節簡單的對 jiffies 進行介紹,下面將在低分辨率定時器和高分辨率定時器中對 jiffies 進行實際的應用。

發佈了57 篇原創文章 · 獲贊 65 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章