linux 多核 系统时钟,Linux中的时间
1. Linux中time相關概念
1.1 real time
指的是實際流逝的時間,又稱為Wall Clock Time(墻上時間)。
比如,time命令統計出的real time指的是該進程從開始運行到運行結束所消耗的時間。在這段時間內不僅僅執行了該進程,其他進程的時間片也得到了輪轉。
1.2 process time
指的是執行某進程所消耗的CPU time。CPU time指的是執行該進程有關代碼所花的時間,分為User CPU time和System CPU time兩部分。
User CPU time指的是在用戶態執行該進程的代碼所花費的時間,不統計該進程阻塞花費的時間,也不統計其他進程的時間片。
System CPU time指的是在內核態執行該進程的代碼所花費的時間,不統計該進程阻塞花費的時間,也不統計其他進程的時間片。。
其實,我覺得“該進程阻塞花費的時間”和“其他進程的時間片” 是一個意思。因為,進程阻塞時,內核會調度其他進程執行,所以我覺得這兩個是一個意思。
需要注意,Real time != User CPU time + System CPU time。兩個原因:
對于多核處理器上跑的多線程程序,會出現real time < User CPU time + System CPU time的情況。
畢竟計算機上不止一個進程在跑,real time中還統計了其他進程的時間片。
1.3 hardware clock
指計算機中電池供電的硬件時鐘,記錄了當前的墻上時間,又被稱為RTC(Real Time Clock)。內核在啟動時會讀取該硬件時鐘,來初始化內核中的軟件時鐘(Software Clock)。
1.4 software clock, HZ, and jiffy
software clock指的是內核維護的軟件時鐘。需要設置timeout的系統調用(例如,select,sigtimedwait)以及測量cpu time的系統調用(例如,getrusage)的準確度(accuracy)由軟件時鐘的精度(precision / resolution)決定。
Linux內核維護的軟件時鐘的精度是jiffy,也就是說軟件時鐘用jiffy衡量時間。jiffy對應的real time由內核中的常量HZ決定,jiffy = 1 / HZ。HZ的值可人為調節,可取的值在不同的內核版本和不同的硬件平臺下也不一樣。在i386平臺下,內核版本2.6.0后,HZ的取值可以達到1000,意味著jiffy對應0.001秒。
那么為什么設置timeout的系統調用和測量cpu time的系統調用的準確度受jiffy的限制呢?原因如下。
cpu里面有可編程間隔定時器PIT,(Programmable interval timer),目前x86-64/arm/8051-based的絕大多數cpu/mcu都是內置PIT的,PIT以一個可調節的時間間隔,即jiffy,觸發時鐘中斷,使得操作系統的時鐘中斷處理程序可以可調節地周期性運行。時鐘中斷處理程序負責維護所有的軟件定時器,在當前進程的時間片用光,或有定時器觸發時執行進程調度(線程調度)。時鐘中斷處理程序還負責維護軟件時鐘。因此,軟件時鐘的精度以及timer相關系統調用的精度都由jiffy限制。
1.5 High-resolution timers
在內核版本2.6.21之前,timer and sleep system calls 的準確度由jiffy限制。自從內核版本2.6.21之開始,Linux開始支持高精度定時器(High-resolution timers, HRTs)。
在支持HRTs的系統上,timer and sleep system calls 的準確度不再受jiffy限制,可以達到硬件級別的準確度。可以通過clock_getres()返回的時鐘的精度判斷系統是否支持高精度定時器。
sleep system calls 包括:
1.6 Epoch
Unix系統使用從1970-01-01 00:00:00 +0000 (UTC)到現在的秒數表示時間。1970-01-01 00:00:00 +0000 (UTC)這個時間點稱為Epoch。
2. 獲取時間
2.1 結構體
目前所知,表示時間只有兩種結構體timeval和timespec,它們的區別主要是精度不同,有些函數的參數使用timeval,有些使用timespec。
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
2.2 函數
Linux中獲取時間的函數有多種,這里我只提gettimeofday()和clock_gettime()。
2.2.1 gettimeofday()
int gettimeofday(struct timeval *tv, struct timezone *tz);
gettimeofday()是系統調用,用于獲取從Epoch開始到現在的時間,精度是微秒。
各種資料表明,gettimeofday()讀取的是內核中的xtime變量的值,xtime每個時鐘中斷更新一次,其精度受限于jiffy。既然是這樣,那么為什么gettimeofday()的精度是微秒呢?經過我查閱資料,jiffy雖然會影響軟件時鐘的精度,但是gettimeofday()不是簡單地讀取xtime,gettimeofday()的實現仍然會依賴于硬件時鐘。更具體的解釋請查看[7]。
我個人認為,gettimeofday()的精度和內核是否支持高精度定時器并沒有關系。一個是讀取時間,一個是定時器,兩者是不同的概念。查閱資料,沒發現有人明確講這個,以后遇到了再做補充吧。
2.2.2 clock_gettime()
int clock_getres(clockid_t clk_id, struct timespec *res);
int clock_gettime(clockid_t clk_id, struct timespec *tp);
int clock_settime(clockid_t clk_id, const struct timespec *tp);
通過上面的接口可以訪問多個時鐘,這些時鐘表示不同的含義。上面的接口中,用戶需要通過clk_id指定對哪個時鐘進行操作。其中clock_gettime()可以獲取指定時鐘的時間,clock_getres()可以獲取指定時鐘的精度。這些時鐘的更新原理并不清楚,但是可以肯定的是,其精度和內核是否支持高精度定時器密切相關。因為,多個資料提到可以使用clock_getres()得到的精度判斷內核是否支持高精度定時器。
clk_id的值:
CLOCK_REALTIME 墻上時間,真實的時間,但是受系統時鐘(system clock)改變的影響,例如用戶調用adjtime函數改變了系統時鐘,那么該墻上時間就會隨之改變。
CLOCK_MONOTONIC 該時鐘用于測量相對的real time,該時鐘和實際的時間相同的速度流逝,并且不被系統時鐘(system clock)的手動/自動改變所影響。
CLOCK_PROCESS_CPUTIME_ID 用于測量進程所用的CPU time。
CLOCK_THREAD_CPUTIME_ID 用于測量線程所用的CPU time。
int timer_create (clockid_t clockid, struct sigevent *evp, timer_t *timerid);
該系統調用用于創建定時器,參數clk_id用于指定該定時器使用的時鐘。該系統調用創建的定時器是高精度定時器。因此,我們使用clock_getres()得到的精度肯定應該小于jiffy。這就印證了之前說的,可以通過clock_getres()查看時鐘的精度來判斷內核是否支持高精度定時器。我自己使用clock_getres()測試的各時鐘的精度是1ns,表示內核支持高精度定時器。
3. 某些系統調用的time accuracy
sleep的參數是秒,accuracy可以達到1秒。Linux下其由nanosleep實現,
usleep的參數是微秒,但是有人說其accuracy不是微秒,說它仍是由時間中斷實現的,本人還沒有找到資料證明usleep究竟有沒有使用HRTs。
nanosleep的參數是納秒,其由HRTs實現,使用CLOCK_MONOTONIC測量時間,不受jiffy限制,accuracy具體可以達到多少不清楚,但是應該可以達到微秒級別。
select的參數是微秒,別人測試accuracy可以達到微秒,有人說其由HRTs實現,但是本人未找到更具體的資料。
因此,選擇延時函數應該一步到位直接用nanosleep。
4. Reference
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的linux 多核 系统时钟,Linux中的时间的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 更改父进程名称,[Linux
- 下一篇: linux 查看系统组账号密码是什么,L