博客
希望我們能(néng)與您分享和探讨成(chéng)長(cháng)中的點點滴滴
通過(guò)DT10檢測多任務阻塞死鎖問題
分享到
DT10是新一代的動态測試工具,可以長(cháng)時(shí)間跟蹤記錄目标程序執行情況,獲取目标程序動态執行數據,幫助進(jìn)行難于重現的Bug錯誤分析,覆蓋率檢測,性能(néng)測試,變量跟蹤,多任務程序等等功能(néng)。
VxWorks在國(guó)内航天軍工、軌道(dào)交通等實時(shí)性要求較高的領域應用非常廣泛,其提供多任務,中斷等機制較好(hǎo)的滿足實時(shí)嵌入式領域的需求,然而開(kāi)發(fā)VxWorks多任務程序過(guò)程中,常常碰到令人頭疼的多任務程序阻塞或死鎖等問題,例如某個task所占用時(shí)間過(guò)長(cháng)導緻其他task不能(néng)正常執行等等問題。
本文介紹如何通過(guò)DT10檢測和調試VxWorks程序多任務阻塞死鎖相關問題。
一、VxWorks環境
啓動FTP Server,并設置Users/rights…
啓動VxWorks目标闆,如下圖所示VxWorks啓動成(chéng)功:
啓動Target Server和Shell:
二、兩(liǎng)個簡單Tornado事(shì)例程序
Multi_Task.c
“
#include "vxworks.h"
#include "semLib.h"
#include "stdio.h"
#define TEST_NUM 10
SEM_ID semB;
int global;
int isTask1Running=1;
int isTask2Running=1;
static void task1(void)
{
int i=0;
while(i<TEST_NUM)
{
printf("<taske1
semTake(semB,WAIT_FOREVER);
printf("<taske1>
global++;
printf("<taske1>
taskDelay(100);
semGive(semB);
printf("
i++;
}
isTask1Running=0;
}
static void task2(void)
{
int i=0;
while(i<TEST_NUM)
{
printf("<taske2>
semTake(semB,WAIT_FOREVER);
printf("
global--;
printf("
taskDelay(200);
semGive(semB);
printf("<taske2>
i++;
}
isTask2Running=0;
}
{
while((isTask1Running==1)||(isTask2Running==1))
{
taskDelay(100);
}
printf("Bye Bye, Both Task1 and Task2 are finished!");
}
{
int taskId1,taskId2;
int t1_pri=91;
int t2_pri=90;
semB=semBCreate(SEM_Q_FIFO,SEM_FULL);
taskId1=taskSpawn("t1",t1_pri,0x100,0x1000,task1,
0,0,0,0,0,0,0,0,0,0);
taskId2=taskSpawn("t2",t2_pri,0x100,0x1000,task2,
0,0,0,0,0,0,0,0,0,0);
taskId2=taskSpawn("t3",t1_pri+1,0x100,0x1000,task3,
0,0,0,0,0,0,0,0,0,0);
}
#include "semLib.h"
#include "taskLib.h"
#include "stdio.h"
voidtaskB();
SEM_ID sem_2;
{
sem_2 = semMCreate(SEM_Q_FIFO);
0,0,0,0,0,0,0,0,0,0);
0,0,0,0,0,0,0,0,0,0);
}
the 2 tasks
-------------------------------------------------*/
voidtaskA()
{
semTake(sem_1, WAIT_FOREVER);
printf("Task A took sem_1, try to take sem_2\n");
}
{
semTake(sem_2, WAIT_FOREVER);
printf("Task B took sem_2, try to take sem_1\n");
}
”
上述兩(liǎng)段程序均使用了VxWorks庫函數taskSpawn創建多個task。 multi_task.c文件中創建了三個task,task1, task2會(huì)設置标志isTask1Running, isTask2Running,當task1,task2結束後(hòu),task3才結束。Dead_lock.c文件中創建taskA, taskB,并通過(guò)信号量進(jìn)行同步。當然,如果你仔細研究代碼,這(zhè)兩(liǎng)段代碼中,均存在某個task不能(néng)正常結束的情況。
下面(miàn)我們將(jiāng)通過(guò)DT10提供的相關debug和測試的功能(néng),幫助查找并定位相關問題。
三、創建DT10工程
在DT10中點擊File->New創建一個工程,并設定工程名稱,指定被(bèi)測試文件目錄和DT10工程存放路徑,設定Connection方式(DT10支持多種(zhǒng)與目标機的連接方式)爲Ethernet(Without Tracer),工程創建好(hǎo)後(hòu),如下圖:
然後(hòu)點擊Plan->New Test Point Insertion…,對(duì)test.c文件自動插入FuncIn, FuncOut測試點。測試點插入完畢後(hòu),如下圖。DT10除了支持FuncIn,FuncOut測試點,還(hái)支持CPU壓力測試點,變量測試點,Event Trigger測試點等,幫助用戶對(duì)系統的CPU,任務,變量等進(jìn)行監控。
測試點插入後(hòu),我們在VxWorks構建環境Tornado中重新對(duì)上述項目進(jìn)行編譯鏈接,如下圖:
四、執行程序并收集測試結果
1. 啓動DT10監聽測試結果程序,如下圖:
2. 在Tornado Shell中啓動被(bèi)測試程序,直接在Shell中鍵入vxmain即可,如下圖:
五、分析測試結果
通過(guò)DT10自動插入測試點,程序在執行過(guò)程中,在每個測試點位置,目标程序會(huì)發(fā)出一個信号告知DT10程序執行到該測試點,這(zhè)樣(yàng)DT10收集所有測試日志數據後(hòu),然後(hòu)通過(guò)DT10的分析功能(néng),可以得到包括每個函數的執行時(shí)間,代碼的覆蓋率信息,以及程序執行路徑等圖形化報告,下面(miàn)我們重點介紹通過(guò)DT10的哪些功能(néng),幫助我們定位程序死鎖或阻塞的問題。
1. 通過(guò)測試日志了解任務阻塞或死鎖情況
首先我們看如何通過(guò)DT10的測試日志幫我們查找到任務死鎖的問題。如下圖,我們看到DT10的獲取到的測試日志報告:
結論:通過(guò)DT10測試日志中的FuncIn, FuncOut測試點,很容易找到目标程序運行過(guò)程中是否存在某個任務或者函數被(bèi)阻塞,這(zhè)對(duì)于同時(shí)啓動很多個task的程序而言,可以了解哪些任務是否存在阻塞情況。
2. 通過(guò)覆蓋率信息查看任務函數執行完整情況
另外通過(guò)DT10的覆蓋率信息,也可以從側面(miàn)了解某個函數或任務是否被(bèi)執行完整,是否發(fā)生阻塞導緻任務函數未退出。
結論:通過(guò)覆蓋率測試,一方面(miàn),使得在軟件測試過(guò)程中,可以幫助我們了解測試是否完整,測試用例是否存在遺漏,被(bèi)測試代碼是否存在冗餘;另外一方面(miàn),覆蓋率的信息對(duì)于我們調試代碼也有一定的幫助;
3. 通過(guò)DT10的函數執行時(shí)間了解更多信息
通過(guò)DT10的函數執行時(shí)間報告,可以知道(dào)每個函數的執行時(shí)間,并且該執行時(shí)間精确到納秒級,同時(shí)可以知道(dào)每個函數執行的次數。如下圖:
我們看到該例程中,vxmain和taskB函數執行次數爲1次,執行時(shí)間爲883us和1116us,而taskA的執行次數爲0,執行時(shí)間爲0。這(zhè)樣(yàng)對(duì)于程序員,即可重點關注taskA是否存在問題。除了本例程中這(zhè)種(zhǒng)情況,在實際程序中,程序中的任務可能(néng)會(huì)執行成(chéng)千上萬次,如果在DT10的函數執行時(shí)間報告中,發(fā)現某函數或者任務的某次執行時(shí)間特别長(cháng),舉例,比如某個TaskC,執行次數爲9999次,其中9998次的執行時(shí)間都(dōu)爲1ms左右,另外有一次執行時(shí)間卻爲30s,那麼(me)就(jiù)需要仔細查看這(zhè)一次30s函數執行過(guò)程是什麼(me)邏輯路徑。通過(guò)DT10可以看到每次代碼執行路徑,從而精确查看爲什麼(me)本次執行時(shí)間爲30s,是否存在問題。這(zhè)種(zhǒng)情況在多任務程序中經(jīng)常碰到,比如某個低優先級的任務可能(néng)被(bèi)其它高優先級的任務阻塞,從而導緻該任務執行時(shí)間變長(cháng)。
結論:通過(guò)DT10了解每個函數執行時(shí)間,執行次數,以及每次執行過(guò)程中代碼執行邏輯路徑,從而幫助用戶更細緻的了解代碼執行情況,幫助用戶定位和分析代碼中隐藏的bug。
上面(miàn)重點對(duì)dead_lock.c的結果重點進(jìn)行分析了,對(duì)于multi_task.c的分析類似。有興趣試用并了解DT10的朋友可以聯系我們申請試用。