如何讓jiffies 佔用 jiffies_64 的低32位

轉載自:http://www.groad.net/bbs/thread-3352-1-1.html


在 Linux 內核中,jiffies 用於記錄系統自啓動到當前時刻系統時鐘所產生的滴答數。 


每一秒系統時鐘的中斷次數等於 HZ 的值,比如一般的 PC 中 PC 的值定義爲 1000,也就是說,一秒鐘內系統要收到 1000 次的時鐘中斷;同樣,jiffies 的值在一秒鐘內增加 HZ 。 


系統自啓動到當前時刻爲止運行了 jiffies/HZ 秒。 


在 include/linux/jiffies.h 中有 jiffies 的聲明:

extern unsigned long volatile __jiffy_data jiffies;

由此可見,該變量在 32 位系統中爲 32 位無符號整型;在 64 位系統中爲 64 位無符號整型。如果只用 jiffies 的話,那麼只要 49.7 天就會發生溢出,而溢出會給內核時間度量帶來混亂和其他潛在的未知問題。 


因此,2.6 內核中引入了一個 64 位的無符號整型變量 jiffies_64 。在 1000HZ 的情況下,該變量要在運行幾億年都不會發出溢出,從而有效的防治了溢出導致的潛在問題。jiffies_64 也在 include/linux/jiffies.h 中有聲明: 

extern u64 __jiffy_data jiffies_64;

上面,u64 爲 unsigned long long 類型。 
爲了保持兼容性及訪問效率,內核中仍然保留了 jiffies 變量,因爲大量的驅動程序使用該變量來進行一些與時間相關的操作。 


通過鏈接器腳本 vmlinux.lds (x86 上位於 arch/x86/kernel 下) 可看到: 
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") 
OUTPUT_ARCH(i386) 
ENTRY(phys_startup_32) 
jiffies = jiffies_64;

這裏使得 jiffies 只佔用了 jiffies_64 的低 32 位。這裏可能會有疑問,鏈接器腳本如何得知這兩個定義在別的文件裏的變量?long long 型變量賦值給 long 型變量怎麼不會發出警告? 


關於上面的疑問,涉及到鏈接器中的一個重要的概念: 
在目標文件內定義的符號可以在鏈接器腳本內賦值,此時該符號應試被定義爲全局的。每個符號都對應了一個地址,在鏈接器中的複製就是更改這個符號對應的地址。所以,這和 C 語言中的賦值是完全不同的概念!C 中是賦值,鏈接器中是改變地址,所以不存在發出類型不相符的警告問題。 


下面代碼模擬這一過程: 


鏈接代碼 jiffies.lds: 

OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") 


OUTPUT_ARCH(i386) 


jiffies = jiffies_64;

用戶態程序代碼: 

#include <stdio.h> 
 
 
unsigned long long jiffies_64 = 0x112345678; 
unsigned long jiffies; 
 
 
int main() 
{ 
        printf ("jiffies_64 = 0x%llx\n", jiffies_64); 
        printf ("jiffies_64 = %p\n", &jiffies_64); 
 
 
        printf ("jiffies = 0x%lx\n", jiffies); 
        printf ("jiffies = %p\n", &jiffies); 
        return (0); 
} 

由輸出可見,jiffies 的地址和 jiffies_64 是一樣的,不同的是在程序中體現的長度不同罷了。到此,也可以看到,鏈接器對定義在目標文件中的全局變量(同名全局符號)是可見的。 

另外,jiffies_64 變量會被初始化爲 INITIAL_JIFFIES ,該值定義在文件 include/linux/jiffies.h 中:

/*
 * Have the 32 bit jiffies value wrap 5 minutes after boot
 * so jiffies wrap bugs show up earlier.
 */
#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))

這樣,就使得系統在啓動後 5 分鐘時發生 jiffies 迴繞。這麼做有利於在早期設備驅動程序因 jiffies 迴繞導致的邏輯錯誤,方便驅動程序的開發。

在設備驅動程序中,通常使用 jiffies 變量。因爲在 32 位的系統中訪問 64 位的 jiffies_64 沒有直接訪問 jiffies 來得快,因爲在 32 位系統中訪問 64 位變量需要進行兩次內存訪問,而且在兩次內存訪問中可能不是原子的,且可能會被中斷,從而造成讀取數據的不正確。對於需要訪問 jiffies_64 變量(一般在驅動程序中很少訪問 jiffies_64,通常只有內核核心代碼纔會訪問),內核提供了 get_jiffies_64() 來訪問,該函數採用了加鎖機制,以防止讀取數據的不正確。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章