Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> 關於 Linux

Linux 內核全局變量 jiffies 深度解析:時間計算、64位擴展、回繞處理與內核定時器應用

編輯:關於 Linux

jiffies 是 Linux 內核時間子系統的心跳計數器,定義為 unsigned long 類型,記錄系統啟動以來的時鐘中斷次數。理解其數據結構、轉換宏、64位擴展 jiffies_64、回繞處理機制,是內核開發者、驅動工程師掌握精準定時、延遲控制、超時判斷的核心技能。本文從底層定義到應用層最佳實踐,全景解析 jiffies 體系。

jiffies 內存佈局示意圖

核心定義與類型


// include/linux/jiffies.h
extern u64 __jiffy_data jiffies_64;      // 64 位完整計數器
extern unsigned long volatile __jiffy_data jiffies;  // 32 位低位別名
  • HZ:每秒時鐘中斷頻率 (架構相關,x86 典型 100/250/1000)
  • 系統運行秒數 = jiffies / HZ
  • 秒轉 jiffies = seconds * HZ
  • 類型鐵律:jiffies 必須用 unsigned long 存儲,任何有符號/浮點類型均錯誤

32位/64位架構差異與 get_jiffies_64()

架構jiffies_64 與 jiffies 關係get_jiffies_64() 實現
64 位 (x86_64, arm64)指向同一變量直接返回 jiffies
32 位 (i386, arm)jiffies = jiffies_64 低 32 位需在 xtime_lock 序列鎖保護下讀取完整 64 位值

// 32 位實現片段
u64 get_jiffies_64(void) {
    unsigned long seq;
    u64 ret;
    do {
        seq = read_seqbegin(&xtime_lock);
        ret = jiffies_64;
    } while (read_seqretry(&xtime_lock, seq));
    return ret;
}

最佳實踐:統一使用 get_jiffies_64() 獲取完整計數,避免 32 位截斷導致長時間運行邏輯錯誤。

jiffies 回繞與時間比較宏

32 位 jiffies 最大值 2^32-1,對應運行時間:

  • HZ=100 → 約 497 天
  • HZ=1000 → 約 49.7 天

超過週期將回繞歸零。內核提供四組有符號減法比較宏,正確處理回繞:


// include/linux/jiffies.h
#define time_after(a,b)   ((long)(b) - (long)(a) < 0)   // a 在 b 之後
#define time_before(a,b)  time_after(b,a)                // a 在 b 之前
#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)  // a 在 b 之後或相等
#define time_before_eq(a,b) time_after_eq(b,a)           // a 在 b 之前或相等

// 64 位版本 (需配合 get_jiffies_64())
#define time_after64(a,b)   ((s64)(b) - (s64)(a) < 0)
#define time_before64(a,b)  time_after64(b,a)
#define time_after_eq64(a,b) ((s64)(a) - (s64)(b) >= 0)
#define time_before_eq64(a,b) time_after_eq64(b,a)

使用鐵律:所有涉及 jiffies 比較的邏輯,必須使用上述宏,禁止直接用 >/< 比較。

實戰應用模式

模式 1:非阻塞延遲檢查 (輪詢/狀態機)


unsigned long timeout = jiffies + msecs_to_jiffies(5000);  // 5 秒後超時
while (!condition_met) {
    if (time_after(jiffies, timeout)) {
        return -ETIMEDOUT;
    }
    cpu_relax();  // 或 schedule() 讓出 CPU
}

模式 2:定時器動態修改 (add_timer/mod_timer)


struct timer_list my_timer;
void my_callback(struct timer_list *t) {
    // 處理邏輯
    mod_timer(t, jiffies + msecs_to_jiffies(1000));  // 重新安排 1 秒後
}
timer_setup(&my_timer, my_callback, 0);
mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000));  // 首次啟動

模式 3:超時參數傳遞 (msleep/msleep_interruptible)


// 睡眠指定毫秒 (可被信號打斷)
msleep_interruptible(2000);  // 2 秒
// 精確忙等待 (極短延遲 < 1ms)
udelay(500);  // 500 微秒
ndelay(100);  // 100 納秒

用戶空間與 HZ 可見性

  • 用戶程序無法直接訪問 jiffies (內核符號未導出)
  • 可通過 sysconf(_SC_CLK_TCK) 獲取用戶空間時鐘節拍 (通常 100)
  • /proc/timer_stats (需內核配置) 可觀測定時器分布

避坑指南

錯誤模式後果修正
直接比較 if (jiffies > timeout)回繞後邏輯永久失效使用 time_after(jiffies, timeout)
32 位系統長延遲用 jiffies 計算49 天後溢出錯誤用 get_jiffies_64() + time_after64
混用有符號/無符號變量存儲負數轉大正數邏輯錯亂統一 unsigned long / u64
在中斷上下文調用睡眠函數內核崩潰 BUG: sleeping function called from invalid context改用 mdelay/udelay/ndelay 或 timer/workqueue

總結

jiffies 是內核時間的基石。掌握 類型鐵律 (unsigned long/u64)、轉換宏 (msecs_to_jiffies 等)、比較宏 (time_after 系列)、64 位擴展 (get_jiffies_64)、回繞安全邏輯 五大核心,即可在驅動開發、內核模塊、嵌入式系統中構建健壯的時間相關邏輯。記住:內核時間不倒流,但計數器會回繞;比較宏是唯一護身符。

Copyright © Windows教程網 All Rights Reserved