不知不觉已经是最后一次的实验了。这一次实验的内容是:
- 在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);
}
<style type="text/css"> <!-- pre {font-family:"DejaVu Sans"} p {margin-bottom:0.21cm} --> </style>
如何实现abort功能的。 我是通过在结构体数组里的一个成员变量abortFlag来控制abort功能的。在用户输入abort命令时,将线程的abortFlag置为1。每个线程在互斥信号量执行完V操作时,查询abortFlag的值,若变为1,则在线程内调用了pthread_exit()结束了自己这个线程;若为0,则线程进行下一次的测试,不受影响。每个线程在执行完一次测试时,就好查询这个结构体中的abortFlag的值,如果为1,则实现abort操作,结束该线程。值得注意的是,如果查询标志位abortFlag值实在V操作之前进行的话,一旦用户输入abort指令,当前进程结束了,但是由于没有执行V操作,所以其他线程会阻塞,而且在接下来用户输入exit命令时就会出错,所以一定要在执行完V操作之后才能查询标志位abortFlag。
除了第一次实验没有写之外,总算坚持把剩下的每一次都写完了。感谢每一个阅读的你!