*本文爲參考各方資料整理而成
文章目錄
1 Cyclictest簡介
實時系統指系統的計算正確性不僅取決於計算的邏輯正確性,還取決於產生結果的時間。一個實時操作系統的實時性能的主要評測指標包括上下文切換時間,搶佔時間,中斷延遲時間,信號量混洗時間。主要測試方法有任務切換時間測試、任務搶佔時間測試、中斷管理性能測試、信號混洗時間測試。
實時性是指調度時任務的響應時間。
Cyclictest是rt-tests下一個使用最廣泛的測試工具,主要用來測試使用內核的延遲,從而判斷內核的實時性。
參數 | 含義 |
---|---|
-a [NUM] –affinity |
在處理器N上運行線程N,如果可能,使用NUM引腳處理NUM的所有線程 |
-b USE –breaktrace=USEC |
調試選項,用於控制實施搶佔補丁中的延遲跟蹤器。當延時大於USEC指定的值時,發送停止跟蹤。USEC,單位爲s |
-c CLOCK --clock=CLOCK |
選擇時鐘 0 = CLOCK_MONOTONIC 單調遞增系統(默認) 1 = CLOCK_REALTIME一天中的時間 |
-C –context |
上下文切換追蹤(與-b一起使用) |
-d DIST –distance=DIST |
線程間隔的距離,默認值爲500 |
-E event |
事件追蹤(與-b一起使用) |
-f –ftrace |
ftrace函數跟蹤(通常與-b 配套使用,其實通常使用 -b 即可,不使用 -f ) |
-i INTV –interval=INTV |
線程的基本間隔,默認爲1000(單位爲s) |
-I –irqsoff |
Irfsoff tracing(與-b一起使用) |
-l LOOPS –loops=LOOPS |
循環的個數,默認爲0(無窮個) |
-m --mlockall |
鎖定當前和將來的內存分配 |
-n –nanosleep |
使用 clock_nanosleep |
-h HISTNUM –histogram=US |
在執行完後在標準輸出設備上畫出延遲的直方圖(很多線程有相同的權限)US爲最大的跟蹤時間限制,這個在下面介紹實例時可以用到,結合gnuplot 可以畫出我們測試的結果圖。 |
-p PRIO –prio=PRIO |
最高優先級線程的優先級,使用方法: -p 90/–prio=90 |
-q –quiet |
使用-q 參數運行時不打印信息,只在退出時打印概要內容,結合-h HISTNUM參數會在退出時打印HISTNUM 行統計信息以及一個總的概要信息。 |
2 Cyclictest測試原理
主函數:
int main(int argc, char **argv)
{ ...
stat->min = 1000000;
stat->max = 0;
stat->avg = 0.0;
stat->threadstarted = 1;
status = pthread_create(&stat->thread, &attr, timerthread, par);
...
}
測試線程:
void *timerthread(void *param)
{ ...
interval.tv_sec = par->interval // 首先將參數中的間隔數賦給函數中的間隔數
interval.tv_nsec = (par->interval % USEC_PER_SEC) * 1000;
...
/* Get current time */
clock_gettime(par->clock, &now); // 獲取當前時間,存在 now 中
next = now; //\
next.tv_sec += interval.tv_sec; // = 這三行是將當前時間(now 的值)加上間隔數(interval)算出下次間隔的時間,存在next
next.tv_nsec += interval.tv_nsec; ///
tsnorm(&next);
...
/* Wait for next period */ 等到下次循環
...
if ((ret = clock_gettime(par->clock, &now))) { //下次循環中記錄循環時的時間到now 中,此時now 值中存的數是真實的下次循環的值,而上面存在next 的值是上次循環加上間隔值所以是理論上的下個循環的值。
if (ret != EINTR)
warn("clock_getttime() failed. errno: %d\n", errno);
goto out;
}
if (use_nsecs)
diff = calcdiff_ns(now, next); // 上面已經說過了,now 中是下次循環的真值,而next是理論的值,所以兩者的差就是延時!延時賦值給diff
else
diff = calcdiff(now, next);
if (diff < stat->min) // 假如延時比min 小,將min 改爲這個更小的延時值diff
stat->min = diff;
if (diff > stat->max) { // 假如延時比max 大,將max 改爲這個更大的延時值diff
stat->max = diff;
if (refresh_on_max)
pthread_cond_signal(&refresh_on_max_cond);
}
stat->avg += (double) diff; // 計算新的平均延時
...
/* Update the histogram */ // 更新histogram中存的延時統計數據
if (histogram) {
if (diff >= histogram) { // 假如延時比histogram大,添加一次溢出
stat->hist_overflow++;
if (stat->num_outliers < histogram)
stat->outliers[stat->num_outliers++] = stat->cycles;
}
else // 如果沒有溢出,將histogram 中的相應值加1
stat->hist_array[diff]++;
}
stat->cycles++; // 循環加1
next.tv_sec += interval.tv_sec; // 繼續計算下次循環的值 ...
next.tv_nsec += interval.tv_nsec;
...
}
具體測試時通過創建線程,在線程中進行測試以及記錄.剛開始記錄開始時間爲,間隔時間爲 l,理論值即爲 +l,在執行完之後再次記錄時間,延時即爲 -(+l).
3 Cyclictest安裝
3.1 基於包管理軟件安裝
Debian/Ubuntu系統下可以直接使用apt-get install rt-tests來安裝cyclictest。
#sudo yum install numactl-devel #CentOS安裝
#apt-get install libnuma-dev #Ubuntu安裝
3.2 基於git源碼安裝
從Git存儲庫獲取最新的源代碼,執行命令git clone git://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git或從存檔中獲取已發佈的tarball,解壓縮在預訂的目錄下,並在源目錄下運行make,
(1)拷貝Cyclictest的git倉庫
git clone git://git.kernel.org/pub/scm/utils/rt-tests/rt-tests.git
(2)進入git倉庫
cd rt-tests
(3)創建一個分支,命名爲testing
git branch testing
(4)切換到testing分支
git checkout testing
*(5)查看最新的穩定分支
git checkout origin/stable/v1.0
*(6)查看當前分支
git branch
(7)編譯
make
*(8)交叉編譯,修改Makefile中的編譯器
make CROSS_COMPILE=arm-v4t-linux-gnueabi
4 cyclictest運行
確保是root或使用sudo運行cyclictest,如果沒有參數,cyclictest會創建一個帶有1ms間隔計時器的線程。
#運行5個線程,線程優先級80,無限循環
sudo cyclictest -t 5 -p 80 -n
#clock_nanosleep 線程優先級80,間隔10000微秒,10000次循環,無負載
cyclictest -t1 -p 80 -n -i 10000 -l 10000
#POSIX間隔計時器 線程優先級80,間隔10000微秒,10000次循環,無負載
cyclictest -t1 -p 80 -i 10000 -l 10000
5 Cyclictest測試結果分析
sudo cyclictest -t1 -p 80 -n -i 10000 -l 10000
結果如下:
T: 0 (17769) P:80 I:10000 C: 10000 Min: 3 Act: 13 Avg: 14 Max: 36
結果分析:
T: 0 序號爲0的線程
P: 0 線程優先級爲0
C: 9397 計數器。線程的時間間隔每達到一次,計數器加1
I: 1000 時間間隔爲1000微秒(us)
Min: 最小延時(us)
Act: 最近一次的延時(us)
Avg:平均延時(us)
Max: 最大延時(us)
6 實時操作系統的實時性能指標
6.1 指標1 中斷響應時間(可屏蔽中斷)
計算機接收到中斷信號到操作系統作出響應,並完成切換轉入中斷服務程序的時間。對於搶先式內核,要先調用一個特定的函數,該函數通知內核即將進行中斷服務,使得內核可以跟蹤中斷的嵌套。搶先式內核的中斷響應時間由下式給出:
中斷響應時間=關中斷的最長時間+保護CPU內部寄存器的時間+進入中斷服務函數的執行時間+開始執行中斷服務例程(ISR)的第一條指令時間中斷響應時間是系統在最壞情況下響應中斷的時間,某系統100次中有99次在50ms之內響應中斷,只有一次響應中斷的時間是250ms,只能認爲中斷響應時間是250ms。
6.2 指標2 任務切換時間
除爲中斷處理提供確定性外,實時處理也需要支持週期性間隔的任務調度。大量控制系統要求週期性採樣與處理。某個特定任務必須按照固定的週期(p)執行,從而確保系統的穩定性。考慮一下汽車的防抱死系統(ABS)。控制系統對車輛的每個車輪的轉速進行採樣(每秒最多20次)並控制每個制動器的壓力(防止它鎖死)。爲了保持控制系統的正常工作,傳感器的採樣與控制必須按照一定的週期間隔。這意味着必須搶佔其他處理,以便ABS任務能按照期望的週期執行。
當多任務內核決定運行另外的任務時,它把正在運行任務的當前狀態(即CPU寄存器中的全部內容)保存到任務自己的棧區之中。然後把下一個將要運行的任務的當前狀態從該任務的棧中重新裝入CPU 的寄存器,並開始下一個任務的運行。這個過程就稱爲任務切換。做任務切換所需要的時間取決於CPU有多少寄存器要入棧。CPU 的寄存器越多,額外負荷就越重。
7 參考鏈接
編譯RT-tests進行Linux實時性測試
Ubuntu的rt-tests包
Git 源代碼
實時操作系統
cyclictest 測試以及原理淺談
cyclictest 的使用
cyclictest–(zc7045)實時性能測試及原理
Linux 實時性能測試工具——Cyclictest 的使用與分析
實時Linux內核的編譯安裝(PREEMPT_RT)以及測試
實時系統性能測試指標及方法