linux的核心時間

2021-07-31 13:02:39 字數 4286 閱讀 7315

jiffies在核心中是乙個全域性變數,它用來統計系統啟動以來系統中產生的總節拍數,這個變數定義在include/linux/jiffies.h中,定義形式如下。

unsigned long volatile jiffies;

想要理解jiffies的含義,我們需要首先理解時鐘  節拍率  節拍的概念。

核心一般通過jiffies值來獲取當前時間。儘管該數值表示的是自上次系統啟動到當前的時間間隔,但因為驅動程式的生命期只限於系統的執行期 (uptime),所以也是可行的。驅動程式利用jiffies的當前值來計算不同事件間的時間間隔。

一、時鐘

時鐘使處理器便知道什麼時候能夠執行它的下乙個功能。在linux系統中,時鐘分為硬體時鐘(又叫實時時鐘)軟體時鐘(又叫系統時鐘)。在對核心程式設計中,我們經常用到的是系統時鐘,系統時鐘的主要任務有如下三點:

1.保證系統時間的正確性。

2.防止程序超額使用cpu。

3.記錄cpu和資源消耗的統計時間。

系統時鐘的初始值在系統啟動時,通過讀取硬體時鐘獲得,然後由linux核心來維護。在系統執行中,系統時鐘的更新是根據系統啟動後的時鐘滴答數來更新的。

實時時鐘的主要作用是提供計時和產生精確的時鐘中斷。實時時鐘是用來持久存放系統時間的裝置,即便系統關閉後,它也可以靠主機板上的微型電池提供的電力保持系統的計時。

二、節拍率hz

linux核心每隔固定週期會發出timer interrupt (irq 0),hz是用來定義每一秒有幾次timer interrupts。舉例來說,hz為1000,代表每秒有1000次timer interrupts。 hz可在編譯核心時設定,如下所示(以核心版本2.6.20-15為例):

節拍率其實就是系統定時器產生中斷的頻率,所謂頻率即指中斷每秒鐘產生多少次中斷,即hz(赫茲)。不同的體系結構的系統而言,節拍率不一定相同。

節拍率(hz)的值可以在檔案include/asm-x86/param.h中看到,定義如下。

#define  hz 1000

三、節拍

節拍就是指系統中連續兩次時鐘中斷的間隔時間,該值等於節拍率分之一,即1/hz。因為系統再啟動時已經設定了hz,所以系統的節拍也可以確定。核心正是利用節拍來計算系統時鐘和系統執行時間的。

三、jiffies變數

jiffies用來統計系統啟動以來系統中產生的總節拍數(記錄著從電腦開機到現在總共的時鐘中斷次數

)。該變數在系統啟動時被初始化為0,接下來沒進行一次時鐘中斷,jiffies自動加1。因此,知道了總的節拍數,然後再除以hz,即可知系統的執行時間(jiffies/hz)。

對於jiffies+hz的含義,jiffies表示當前的系統時鐘中斷數,hz表示一秒後的時鐘中斷的增加量,假設time=jiffies+hz,正如上面所說 ,核心正是利用節拍數來計算系統時鐘和系統執行時間的,則通過jiffies+hz即可間接表示一秒鐘。

如果系統中某個程式執行一段時間後,需要比較該執行時間是否超過一秒,即可通過比較time和程式執行後的jiffies值來判斷是否超過一秒。當然此時,我們需要考慮jiffies變數的迴繞問題,不可直接用if(time > jiffies)來比較,linux系統提供了4個巨集定義來解決使用者空間利用jiffies變數進行時間比較時可能產生的迴繞現象

值得注意的是,jiffies於系統開機時,並非初始化成零,而是被設為-300*hz (arch/i386/kernel/time.c),即代表系統於開機五分鐘後,jiffies便會溢位。那溢位怎麼辦?事實上,linux核心定義幾個macro(timer_after、time_after_eq、time_before與time_before_eq),即便是溢位,也能借由這幾個macro正確地取得jiffies的內容。

硬體給核心提供乙個系統定時器用以計算和管理時間,核心通過程式設計預設系統定時器的頻率,即節拍率(tick rate),每乙個週期稱作乙個tick(節拍)。

可以利用jiffies設定超時等,譬如:

unsigned long timeout =jiffies + tick_rate * 2; // 2秒鐘後超時

if(time_before(jiffies, timeout)

else

核心提供了四個巨集來比較節拍計數,這些巨集定義在檔案中:

time_before(unknown, known)

time_after(unknown, known)

time_before_eq(unknown, known)

time_after_eq(unknown, known)

比較的時候用這些巨集可以避免jiffies由於過大造成的迴繞問題。

/* *

*time_after(a,b) returns true if the time a is after time b.*

* do this with "<0" and ">=0" to only test the sign of the result. a

* good compiler would generate better code (and a really good compiler

* wouldn't care). gcc is currently neither.

*/ #define time_after(a,b) \

(typecheck(unsigned long, a) && \

typecheck(unsigned long, b) && \

((long)(b) - (long)(a) < 0))

#define time_before(a,b) time_after(b,a)

#define time_after_eq(a,b) \

(typecheck(unsigned long, a) && \

typecheck(unsigned long, b) && \

((long)(a) - (long)(b) >= 0))

#define time_before_eq(a,b) time_after_eq(b,a)

在巨集time_after中,首先確保兩個輸入引數a和b的資料型別為unsigned long,然後才執行實際的比較。

unsigned long timeout = jiffies + hz/2; /* timeout in 0.5s */

/* do some work ... */

do_somework();  

/* then see whether we took too long */

if (time_before(jiffies, timeout))  else  

除了系統定時器外,還有乙個與時間有關的時鐘:實時時鐘(rtc),這是乙個硬體時鐘,用來持久存放系統時間,系統關閉後靠主機板上的微型電池保持計時。系統啟動時,核心通過讀取rtc來初始化wall time,並存放在xtime變數中,這是rtc最主要的作用。

要檢查系統上hz的值是什麼,就執行命令

cat kernel/.config | grep '^config_hz='

tick是hz的倒數,意即timer interrupt每發生一次中斷的時間。如hz為250時,tick為4毫秒(millisecond)。

另外,80x86架構定義乙個與jiffies相關的變數jiffies_64 ,此變數64位元,要等到此變數溢位可能要好幾百萬年。因此要等到溢位這刻發生應該很難吧。

jiffies轉換為秒可採用公式:(jiffies/hz)計算,

將秒轉換為jiffies可採用公式:(seconds*hz)計算。

當時鐘中斷發生時,jiffies 值就加1。因此連續累加一年又四個多月後就會溢位(假定hz=100,1個jiffies等於1/100秒,jiffies可記錄的最大秒數為 (2^32 -1)/100=42949672.95秒,約合497天或1.38年),即當取值到達最大值時繼續加1,就變為了0。

核心通過xtime變數儲存牆上時間,該變數是timespec型別的,在linux/time.h中定義如下:

1structtimespec ;

其中,tv_sec是以秒為單位時間,它儲存著從2023年7月1日以來經過的時間,而tv_nsec記錄自上一秒開始經過的納秒數?。

linux核心時間操作

linux核心是通過定時器中斷來跟蹤時間流 使用 hz 巨集表示1秒的時鐘中斷次數,並使用 jiffies 及 jiffies 64 變數來記錄時鐘中斷次數,在系統引導時計數器初始化為 0 1 核心時間比較api,比較jiffies計數器 include int time after unsigne...

Linux核心中的時間函式

ktime t ktime get void 獲取基於clock monotonic的當前時間,返回ktime t格式的資料型別。單調遞增的,一般認為它不會受到ntp的影響,使用者修改牆上時間,不會對這個產生影響。核心一般可以用這個來統計延時時間。ktime t ktime get boottime...

Linux核心獲取系統時間

在linux核心中,常常使用do gettimeofday 函式來得到精確的系統執行時間,尤其在嵌入式中非常常見。很多程式執行,不需要獲取到年月日等資訊,但是需要獲取高精度的系統時間,可以使用這個函式。函式功能和c標準庫中gettimeofday 用法相同。下面 拿去使用吧。include unsi...