生活随笔
收集整理的這篇文章主要介紹了
jiffies
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
?全局變量jiffies用來記錄自系統啟動以來產生的節拍的總數。啟動時,內核將該變量初始化為0,此后,每次時鐘中斷處理程序都會增加該變量的值。一秒內時鐘中斷的次數等于Hz,所以jiffies一秒內增加的值也就是Hz。
?? 系統運行時間以秒為單位,等于jiffies/Hz。
?
注意,jiffies類型為無符號長整型(unsigned long),其他任何類型存放它都不正確。
將以秒為單位的時間轉化為jiffies:
??????????seconds * Hz
將jiffies轉化為以秒為單位的時間:
?????????jiffies / Hz
相比之下,內核中將秒轉換為jiffies用的多些。
?? jiffies定義于文件<linux/Jiffies.h>中:
?
extern?u64?__jiffy_data?jiffies_64; extern?unsigned?long?volatile?__jiffy_data?jiffies;
ld(1)腳本用于連接主內核映像(在x86上位于arch/i386/kernel/vmlinux.lds.S中),然后用jiffies_64變量的初值覆蓋jiffies變量。因此jiffies取整個jiffies_64變量的低32位。
? 訪問jiffies的代碼只會讀取jiffies_64的低32位,通過get_jiffies_64()函數就可以讀取整個64位的值。在64位體系結構上,jiffies_64和jiffies指的是同一個變量。
#if?(BITS_PER_LONG?<?64) u64?get_jiffies_64(void);#else static?inline?u64?get_jiffies_64(void){ ????return?(u64)jiffies;} #endif
?
在<Time.c(kernel)>中 #if?(BITS_PER_LONG?<?64)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;}
?
? 當jiffies的值超過它的最大存放范圍后就會發生溢出。對于32位無符號長整型,最大取值為(2^32)-1,即429496795。如果節拍計數達到了最大值后還要繼續增加,它的值就會回繞到0。
? 內核提供了四個宏來幫助比較節拍計數,它們能正確的處理節拍計數回繞的問題:
?
#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) #define?time_after64(a,b)???/ ????(typecheck(__u64,?a)?&&?/ ?????typecheck(__u64,?b)?&&?/ ?????((__s64)(b)?-?(__s64)(a)?<?0)) #define?time_before64(a,b)??time_after64(b,a) #define?time_after_eq64(a,b)????/ ????(typecheck(__u64,?a)?&&?/ ?????typecheck(__u64,?b)?&&?/ ?????((__s64)(a)?-?(__s64)(b)?>=?0)) #define?time_before_eq64(a,b)???time_after_eq64(b,a)
? 問題提出:
? 在2.6以前的內核中,如果改變內核中的HZ值會給用戶空間中某些程序造成異常結果。因為內核是以節拍數/秒的形式給用戶空間導出這個值的,應用程序便依賴這個特定的HZ值。如果在內核中改變了HZ的定義值,就打破了用戶空間的常量關系---用戶空間并不知道新的HZ值。
? 解決方法:
? 內核更改所有導出的jiffies值。內核定義了USER_HZ來代表用戶空間看到的HZ值。在x86體系結構上,由于HZ值原來一直是100,所以USER_HZ值就定義為100。內核可以使用宏jiffies_to_clock_t()將一個有HZ表示的節拍計數轉換為一個由USER_HZ表示的節拍計數。
?
在<Time.c(kernel)>中 clock_t?jiffies_to_clock_t(long?x) { #if?(TICK_NSEC?%?(NSEC_PER_SEC?/?USER_HZ))?==?0 ????return?x?/?(HZ?/?USER_HZ); #else ????u64?tmp?=?(u64)x?*?TICK_NSEC; ????do_div(tmp,?(NSEC_PER_SEC?/?USER_HZ)); ????return?(long)tmp; #endif } unsigned?long?clock_t_to_jiffies(unsigned?long?x) { #if?(HZ?%?USER_HZ)==0 ????if?(x?>=?~0UL?/?(HZ?/?USER_HZ)) ????????return?~0UL; ????return?x?*?(HZ?/?USER_HZ); #else ????u64?jif; ???? ????if?(x?>=?~0UL?/?HZ?*?USER_HZ) ????????return?~0UL; ???? ????jif?=?x?*?(u64)?HZ; ????do_div(jif,?USER_HZ); ????return?jif; #endif } u64?jiffies_64_to_clock_t(u64?x) { #if?(TICK_NSEC?%?(NSEC_PER_SEC?/?USER_HZ))?==?0 ????do_div(x,?HZ?/?USER_HZ); #else ???? ????x?*=?TICK_NSEC; ????do_div(x,?(NSEC_PER_SEC?/?USER_HZ)); #endif ????return?x; }
在<Div64.h(include/asm-i385)>中 #define?do_div(n,base)?({?/ ????unsigned?long?__upper,?__low,?__high,?__mod,?__base;?/ ????__base?=?(base);?/ ????asm("":"=a"?(__low),?"=d"?(__high):"A"?(n));?/ ????__upper?=?__high;?/ ????if?(__high)?{?/ ????????__upper?=?__high?%?(__base);?/ ????????__high?=?__high?/?(__base);?/ ????}?/ ????asm("divl?%2":"=a"?(__low),?"=d"?(__mod):"rm"?(__base),?"0"?(__low),?"1"?(__upper));?/ ????asm("":"=A"?(n):"a"?(__low),"d"?(__high));?/ ????__mod;?/ })
? 用戶空間期望HZ=USER_HZ,但是如果它們不相等,則由宏完成轉換。
?
總結
以上是生活随笔為你收集整理的jiffies的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。