Liping Zou bio photo

Liping Zou

An Android Developer

Email Twitter Instagram Github

不知不觉已经是最后一次的实验了。这一次实验的内容是:

  1. 在Ubuntu下编写多线程的应用程序memtest.c,解决一个可并行运算的问题。

  2. 在Linux 0.11的进程管理基础上,按照POSIX Threads标准实现内核级线程,使其能支持memtest.c的运行

说来也很遗憾,这个实验我只完成了用户态的实现,内核级完全没有考虑去实现(时间、精力等等多方面的问题)。如果真的要把内核级一并实现,那么这次的实验可以说是最难的一次。

下面简单的说一下实现的思路。

首先设计了一个结构体,用来保存各个线程的信息。

1
2
3
4
5
6
7
8
9
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:停止测试并退出程序。

在识别出用户的命令之后,可以进行的操作有创建线程,并将结构体中的信息标志位的设置,各种信息的打印等等,就不一一赘述了。 对任一被测内存单元,先写入一个数,再从该单元读出,比较写入和读出的数是否相等。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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。

除了第一次实验没有写之外,总算坚持把剩下的每一次都写完了。感谢每一个阅读的你!:)