生活随笔
收集整理的這篇文章主要介紹了
jiffies
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?全局變量jiffies用來記錄自系統(tǒng)啟動(dòng)以來產(chǎn)生的節(jié)拍的總數(shù)。啟動(dòng)時(shí),內(nèi)核將該變量初始化為0,此后,每次時(shí)鐘中斷處理程序都會(huì)增加該變量的值。一秒內(nèi)時(shí)鐘中斷的次數(shù)等于Hz,所以jiffies一秒內(nèi)增加的值也就是Hz。
?? 系統(tǒng)運(yùn)行時(shí)間以秒為單位,等于jiffies/Hz。
?
注意,jiffies類型為無符號(hào)長整型(unsigned long),其他任何類型存放它都不正確。
將以秒為單位的時(shí)間轉(zhuǎn)化為jiffies:
??????????seconds * Hz
將jiffies轉(zhuǎn)化為以秒為單位的時(shí)間:
?????????jiffies / Hz
相比之下,內(nèi)核中將秒轉(zhuǎn)換為jiffies用的多些。
?? jiffies定義于文件<linux/Jiffies.h>中:
?
extern?u64?__jiffy_data?jiffies_64; extern?unsigned?long?volatile?__jiffy_data?jiffies;
ld(1)腳本用于連接主內(nèi)核映像(在x86上位于arch/i386/kernel/vmlinux.lds.S中),然后用jiffies_64變量的初值覆蓋jiffies變量。因此jiffies取整個(gè)jiffies_64變量的低32位。
? 訪問jiffies的代碼只會(huì)讀取jiffies_64的低32位,通過get_jiffies_64()函數(shù)就可以讀取整個(gè)64位的值。在64位體系結(jié)構(gòu)上,jiffies_64和jiffies指的是同一個(gè)變量。
#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;}
?
? 當(dāng)jiffies的值超過它的最大存放范圍后就會(huì)發(fā)生溢出。對(duì)于32位無符號(hào)長整型,最大取值為(2^32)-1,即429496795。如果節(jié)拍計(jì)數(shù)達(dá)到了最大值后還要繼續(xù)增加,它的值就會(huì)回繞到0。
? 內(nèi)核提供了四個(gè)宏來幫助比較節(jié)拍計(jì)數(shù),它們能正確的處理節(jié)拍計(jì)數(shù)回繞的問題:
?
#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以前的內(nèi)核中,如果改變內(nèi)核中的HZ值會(huì)給用戶空間中某些程序造成異常結(jié)果。因?yàn)閮?nèi)核是以節(jié)拍數(shù)/秒的形式給用戶空間導(dǎo)出這個(gè)值的,應(yīng)用程序便依賴這個(gè)特定的HZ值。如果在內(nèi)核中改變了HZ的定義值,就打破了用戶空間的常量關(guān)系---用戶空間并不知道新的HZ值。
? 解決方法:
? 內(nèi)核更改所有導(dǎo)出的jiffies值。內(nèi)核定義了USER_HZ來代表用戶空間看到的HZ值。在x86體系結(jié)構(gòu)上,由于HZ值原來一直是100,所以USER_HZ值就定義為100。內(nèi)核可以使用宏jiffies_to_clock_t()將一個(gè)有HZ表示的節(jié)拍計(jì)數(shù)轉(zhuǎn)換為一個(gè)由USER_HZ表示的節(jié)拍計(jì)數(shù)。
?
在<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,但是如果它們不相等,則由宏完成轉(zhuǎn)換。
?
總結(jié)
以上是生活随笔為你收集整理的jiffies的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。