內核級線程

不知不覺已經是最後一次的實驗了。這一次實驗的內容是:

  1. 在Ubuntu下編寫多線程的應用程序memtest.c,解決一個可並行運算的問題。
  2. 在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函數中,對於用戶輸入的命令進行判斷,並作出相應的操作。用戶輸入的命令有六個:

  1. times number :設置對每個內存單元進行測試的次數。number即次數。每次測試都要測完全部的5種數據。例如,命令“times 5”表示對每個內存單元,每種數據都要測5次。
  2. thread number :設置進行測試工作的線程個數。number即個數。主線程並不算在number內。例如,命令“thread 2”表示同時建立2個工作線程進行併發測試。
  3. go:按照設定的參數建立工作線程,開始測試。主線程仍然在命令行等待用戶命令。
  4. status:打印所有工作線程的工作狀態,包括它們的當前進度和測試結果等。
  5. abort:停止測試。讓所有工作線程都退出。
  6. 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。

除了第一次實驗沒有寫之外,總算堅持把剩下的每一次都寫完了。感謝每一個閱讀的你!


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章