linux時間函數解釋(轉)

1. 時間相關硬件 

計算機系統中的時間主要由三種時鐘硬件提供的:實時時鐘(Real TimeClock,RTC),可編程間隔定時器(Programmable Interval Timer,PIT),時間戳計數器(TimeStampCounter,TSC)。這些時鐘硬件都是基於固定頻率的晶振來提供時鐘方波信號輸入。 

一般說來,Linux內核主要需要兩種類型的時間: 
一類是單步遞增性時鐘,不發送中斷,需要軟件主動去讀取其COUNTER寄存器來獲得時間的。TSC即屬於這一類。 
另一種維持一個固定週期的定時器,以提醒內核或用戶一段時間已經過去了。通過週期性發送中斷達到記時目的。PIT屬於這一類。 

RTC通過主板上的電池來供電,在關機時維持日期和時間。RTC爲整個計算機提供了一個計時標準,是底層的時鐘數據,也被稱爲硬件時鐘CMOS時鐘。 
PIT 定時/計數器所採用的最典型的芯片是Intel8253/8254可編程定時/計數芯片。定時/計數器從RTC接收輸入脈衝,然後開始遞減計數,當計數到零時,產生一個輸出脈衝,引發實時中斷處理程序,然後定時/計數器復位又開始從頭計數。在開機時,操作系統通過獲取RTC中的時間數據來初始化系統時鐘,然後通過定時/計數芯片的向下計數引發時鐘中斷,形成系統時鐘(clocktick),頻率大致在100-1000Hz之間。 
TSC是一個不斷增加的計數器,它在CPU的每個時鐘信號到來時加1。也就是以處理器頻率加1。即在主流處理器上更新頻率可達到上GHz。 

2. 時間相關數據結構 

Linux有兩個重要的數據結構,一個是32位的無符號整數全局變量jiffies,每次時鐘中斷時加1(一般相隔1ms-10ms),linux運行時就是以這個時間來記錄的,如進程時間片更新,執行定時服務等,可以視爲Linux運行的心跳。另一個是全局變量xtime,是timeval結構的變量。用來表示當前時間距UNIX時間基準1970-01-0100:00:00的相對秒數值。其時間精度是納秒(先前的版本爲微秒)。因爲xtime主要供查詢使用,所以xtime的更新被放到timer_interrupt()的後半段執行,和jiffies不同,不是每次時鐘中斷時都執行。因此看起來會比jiffies慢,兩者不同步 

3. 時間相關係統調用 
獲取時間的系統調用主要有兩個time()和gettimeofday() 
time()即簡單的把xtime中的tv_sec返回到用戶空間。單位爲秒。 
gettimeofday()用來獲取精度爲us的當前時間信息和時區信息。首先用當前的jiffies減去上次更新xtime時的jiffies,得到一個修正值即上次修正xtime到目前的差值,但是這個值是ms級精度的。要獲得us精度,需要用當前TSC值減去上次時鐘中斷髮生時的TSC,用這兩個值更新xtime,並將這個值返回到用戶空間。在2.6.20中主要的調用路徑如下: 
sys_gettimeofday()-> 
do_gettimeofday()-> 
offset = time_interpolator_get_offset(); ->  
time_interpolator_get_counter();-> 
time_interpolator_get_cycles();-> 
get_cycles(); -> 
rdtscll(); -> 
get_scheduled_cycles(); -> 
native_read_tsc(); -> 
asm volatile("rdtsc" : "=A" (val));//讀取TSC的值 

4. 獲取精度更高的時間 
在Linux中xtime的精度爲ns,並且有getnstimeofday(),當並沒有作爲系統調用提供。要在用戶空間獲得ns級的時間用戶可以自己實現。可以參考sys_gettimeofday和 getnstimeofday(): 
sys_gettimeofday(struct timeval __user*tv){ 
offset =time_interpolator_get_offset(); 
sec = xtime.tv_sec; 
nsec = xtime.tv_nsec; 
usec = (nsec + offset) / 1000; 
ktv->tv_sec = sec; 
ktv->tv_usec = usec; 
copy_to_user(tv, &ktv,sizeof(ktv)); 


getnstimeofday (struct timespec*tv) 

sec = xtime.tv_sec; 
nsec =xtime.tv_nsec+time_interpolator_get_offset(); 
tv->tv_sec = sec; 
tv->tv_nsec = nsec; 


5. 時鐘同步 
在單處理系統中,因爲系統時間(由時鐘中斷更新)和TSC(由處理器CLK信號更新)都是由硬件負責運轉,獨立運行,所以可能出現不同步的問題(比如Linux時鐘中斷屏蔽時,jiffies不會更新)。Linux會在合適的時間使用TSC對系統時鐘進行校正。 
在多處理系統中,因爲有多個處理器,時鐘中斷是在處理器中廣播的,而由其中一個處理器進行時鐘中斷處理。但是TSC是每個處理器獨自擁有的,需要在各個TSC間進行同步。 
在虛擬系統中(如VMware,Xen), 時鐘中斷由軟件模擬產生,而TSC也不能直接從硬件上讀取,需要虛擬軟件利用處理器提供的能力,在TSC真實的值上進行進一步的處理。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章