做嵌入式虛擬化實驗時,對即時效能的測試一直都是用的cyclictest,它其實代碼只有幾百行,基本的原理也是非常簡單的,但是它用到的API是要注意一下的。
這裡假定cyclictest所用參數為:cyclictest -t1 -n -m -p 80 -i 10000 -l 10000。這裡面與clock相關的設定是:-n指定使用clock_nanosleep();沒有指定-clock,那麼就是用預設的CLOCK_MONOTONIC,而不是CLOCK_REALTIME;沒有指定-r,那麼就是使用預設的absolute
time,而不是relative。cyclictest代碼的關鍵流程是:1. 先用clock_gettime(CLOCK_MONOTONIC,&now)擷取目前時間T1;2. 然後判斷出par->mode是MODE_CLOCK_NANOSLEEP,par->timermode=TIMER_ABSTIME,因而執行clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next, NULL);3. 之後再用clock_gettime( CLOCK_MONOTONIC,&now)擷取目前時間T2,計算T2-(T1+interval)就可以得到latency了。從代碼中看,T1+interval賦值給了next,於是只要計算第二次的now(T2)
- next就可以了。那麼,如果要將cyclictest移植到其他OS中去,clock_gettime和clock_nanosleep是兩個很關鍵的API,要看在其他OS中是否有對應的API可以調用。稍微看了一下clock_gettime在Linux核心中的實現,參考clock_gettime.c:如果是CLOCK_REALTIME,那麼它將調用gettimeofday擷取時間放入struct timeval變數中,然後將其轉換為struct
timespec類型(timeval精度是微妙,timespec精度是納秒)。如果是CLOCK_MONOTONIC,調用hp_timing_gettime。hp_timing_gettime流程如下:1. 先調用__get_clockfreq擷取CPU時鐘頻率freq,也就是主頻;2. 然後調用HP_TIMING_NOW(tsc)擷取目前時間,從變數名稱上看應該是讀的TSC;3. tsc減去當前進程啟動時讀取的TSC4. tsc/freq就可以計算出經過的秒數;(tsc%freq)*10^9 / freq可以計算出經過的納秒數查過一些資料,在x86中,gettimeofday一般也是用TSC來實現的,但是精度只有微妙級。所以,總的來說,clock_gettime就是通過讀取TSC來gettime,這就與HZ的值無關了。另外,我想gettimeofday的實現應是在啟動讀RTC時,將REAL-TIME轉換為TSC值,之後gettimeofday返回這個值加上當前TSC(因為TSC在CPU啟動時是從0開始計數),再轉換為微妙格式。最後提一下,cyclictest的timerthread中,還有判斷par->mode是否為MODE_CYCLIC,這個與本參數的設定無關係,它的作用是不是每測一次iteration後馬上開始下一個,而是指定從本次iteration開始後的某周期時間後開始下次iteration。這就類似於ltp_latency的period測試方式了。