jiffies的迴繞問題及解決方案

2021-07-11 12:24:30 字數 1970 閱讀 5220

一、什麼是jiffies

全域性變數jiffies用來記錄自啟動以來產生的節拍的總數。系統啟動時會將該變數初始化為0,此後,每當時鐘中斷產生時就會增加該變數的值。jiffies和另外乙個變數息息相關:hz。hz是每秒系統產生的時鐘中斷次數,所以jiffies每秒增加的值也就是hz。

jiffies定義於

extern

unsigned

long

volatile jiffies;

從上面的**中我們可以看出,jiffies被宣告為無符號的長整形,在32位的機器上能用的最大值是2^32-1,在64位的機器上能用的最大值就是2^64-1。

二、jiffies迴繞問題

首先,我們來看一下什麼是迴繞。正如我們所說,jiffies有自己的最大值,我們假設機器是32位的,此時jiffies為2^32-1,那麼按照理想情況下一次加1後jiffies的值應該是2^32,但是學過c語言或者是c++語言的同學都知道,如果乙個數加到了它的最大值,在增加時就會回到最小值,這就是迴繞。

根據hz與jiffies的關係,在32位的機器上,如果系統的hz值為100的情況下,jiffies的迴繞時間大約為500天左右,如果hz為1000,那麼迴繞時間將只有50天左右。

當發生迴繞時,會使原來正常的程式產生不正常的結果,例如下面的例子。

unsigned long timeout = jiffies + hz/2; 後超時

/*執行一些任務*/

........

/*然後檢查時間是否過長*/

if(timeout>jiffies)else

使用timeout來檢測程式的執行是否超時,timeout被設為jiffies加上0.5秒,程式執行一些步驟後檢測timeout和jiffies的大小,如果timeout大於jiffies,說明上面這些步驟是在0.5秒內完成的。但是當jiffies出現回環時,上面的檢測就會出現問題,因為jiffies回環後會變成乙個非常小的數,所以timeout肯定會大於jiffies,但是程式卻可能會執行超過0.5秒。

三、如何解決迴繞問題

為了解決迴繞問題,linux中定義了以下四個的比較函式,其中unknown引數一般為jiffies,know引數為要比較的物件,例如上文中timeout。

#define time_after(unknown,known) ((long)(known) - (long)(unknown)<0)

#define time_before(unkonwn,known) ((long)(unknown) - (long)(known)<0)

#define time_after_eq(unknown,known) ((long)(unknown) - (long)(known)>=0)

#define time_before_eq(unknown,known) ((long)(known) -(long)(unknown)>=0)

這四個巨集僅僅是將jiffies和要比較的數值從unsigned long變為了long為什麼就能避免迴繞了呢。

為了便於說明,我們假設jiffies是單位元組的無符號數,範圍為0~255。假如jiffies開始為250,由於是無符號資料,那麼它在機器中實際儲存的補碼為11111010,記為j1;timeout如果被設為252,實際儲存為11111100;而過了一會jiffies發生迴繞編變成了1,實際儲存變為00000001,記為j2。 那麼此時如果按照無符號數比較其大小關係,有:j1j1如果按照有符號數讀取,首先從補碼轉換成原碼:10000110,轉換成十進位制為-6;

timeout按照有符號數讀取,首先從補碼轉換成原碼:10000100,轉換成十進位制為-4;

j2按照有符號數讀取,首先從補碼轉換成原碼:00000001,轉換成十進位制為1;

這樣它們的大小關係為:j1。 這與實際的節拍計數就吻合了,以上核心定義的幾個巨集就是通過這種方式巧妙解決jiffies迴繞問題的。

20090709 問題及解決

20090709 周四 1.個人更新 web service net 個人更新的具體步驟 1 取最新的 2 編譯web service 3 更新客戶端的 service引用 選中service references 資料夾下的具體 service,右擊,選擇 update service refer...

ABA問題及解決

aba問hiyi題 在多執行緒環境下,乙個執行緒需要修改共享變數的值,使用cas操作時,當其他執行緒將該共享變數由a該為b,再將b改為a後,這個執行緒依然可以cas操作成功,因為這個執行緒不能感知這個共享變數被修改過 解決方法 給共享變數增加乙個版本號,在cas操作時不僅比較值是否相等,還比較版本號...

Ubuntu問題及解決

ubuntu問題及解決 在裝好乙個新的ubuntu系統後,對其進行換源後,對其進行更新時,執行如下指令 sudo apt get update sudo apt get full upgrade當執行完sudo apt get full upgrade指令後卻出現了如下錯誤 e unmet depe...