不知不覺已經是最後一次的實驗了。這一次實驗的內容是:
- 在Ubuntu下編寫多線程的應用程序memtest.c,解決一個可並行運算的問題。
- 在Linux 0.11的進程管理基礎上,按照POSIX Threads標準實現內核級線程,使其能支持memtest.c的運行
說來也很遺憾,這個實驗我只完成了用戶態的實現,內核級完全沒有考慮去實現(時間、精力等等多方面的問題)。如果真的要把內核級一併實現,那麼這次的實驗可以說是最難的一次。
下面簡單的說一下實現的思路。
首先設計了一個結構體,用來保存各個線程的信息。
struct info
{
pthread_t id;//線程的ID
int total;//線程測試的內存大小
int begin_addr;//測試的內存的首地址
int stopFlag;
int proInfo;
int abortFlag;
} info[30];
在main函數中,對於用戶輸入的命令進行判斷,並作出相應的操作。用戶輸入的命令有六個:
- times number :設置對每個內存單元進行測試的次數。number即次數。每次測試都要測完全部的5種數據。例如,命令“times 5”表示對每個內存單元,每種數據都要測5次。
- thread number :設置進行測試工作的線程個數。number即個數。主線程並不算在number內。例如,命令“thread 2”表示同時建立2個工作線程進行併發測試。
- go:按照設定的參數建立工作線程,開始測試。主線程仍然在命令行等待用戶命令。
- status:打印所有工作線程的工作狀態,包括它們的當前進度和測試結果等。
- abort:停止測試。讓所有工作線程都退出。
- exit:停止測試並退出程序。
對任一被測內存單元,先寫入一個數,再從該單元讀出,比較寫入和讀出的數是否相等。代碼如下:
void* test(void* tag)
{
int i,j,k;
char* beginAddr;
info[(int)tag].stopFlag = 0; //running
size = SIZE / threadNum;
beginAddr = mem + ((int)tag)*size;
srand(time(NULL));
testData[4] = (char)rand();
for(i=0; i<info[(int)tag].total; i++)
{
pthread_mutex_lock(&mut);
for(j=0; j<times; j++)
{
for(k=0; k<5; k++)
{
*beginAddr = testData[k];
if((*beginAddr)!=testData[k])
{
error = 1;
}
}
}
pthread_mutex_unlock(&mut);
if(info[(int)tag].abortFlag==1)
{
info[(int)tag].stopFlag = 2;//abort
pthread_exit(&(info[(int)tag].abortFlag));
}
info[(int)tag].proInfo++;
beginAddr++;
}
info[(int)tag].stopFlag = 1;//exit
pthread_exit(&error);
}
如何實現abort功能的。 我是通過在結構體數組裏的一個成員變量abortFlag來控制abort功能的。在用戶輸入abort命令時,將線程的abortFlag置爲1。每個線程在互斥信號量執行完V操作時,查詢abortFlag的值,若變爲1,則在線程內調用了pthread_exit()結束了自己這個線程;若爲0,則線程進行下一次的測試,不受影響。每個線程在執行完一次測試時,就好查詢這個結構體中的abortFlag的值,如果爲1,則實現abort操作,結束該線程。值得注意的是,如果查詢標誌位abortFlag值實在V操作之前進行的話,一旦用戶輸入abort指令,當前進程結束了,但是由於沒有執行V操作,所以其他線程會阻塞,而且在接下來用戶輸入exit命令時就會出錯,所以一定要在執行完V操作之後才能查詢標誌位abortFlag。
除了第一次實驗沒有寫之外,總算堅持把剩下的每一次都寫完了。感謝每一個閱讀的你!