实验一
一、实验目的
深刻理解线程和进程的概念,掌握线程与进程在组成成分上的差别,以及与其相适应的通讯方式和应用目标。
二、实验内容
1、以Linux系统进程和线程机制为背景,掌握fork()和clone()系统调用的形式和功能,以及与其相适应的高级通讯方式。由fork派生的子进程之间通过pipe通讯,由clone创建的线程之间通过共享内存通讯,对于后者需要考虑互斥问题。
2、以生产者/消费者问题为例,通过实验理解fork()和clone()两个系统调用的区别。程序要求能够创建4个进程或线程,其中包括两个生产者和两个消费者,生产者和消费者之间能够传递数据。
原书中代码 不再给出:遇到问题如下
1.书中有打印错误 CLONE_SIGNAND 应为 CLONE_SIGHAND
2.在mian中,创建线程的代码段;书中有错误;
int clone_flag,arg,retval;
char *stack;03.
clone_flag = CLONE_VM|CLONE_SIGNAND|CLONE_FS|CLONE_FILES;
int i;
for(i=0;i<2;i++)
{
arg=i;
stack=(char*)malloc(4096);
retval = clone((void*)producer,&(stack[4095]),clone_flag,(void*)&arg);
stack=(char*)malloc(4096);
retval = clone((void*)consumer,&(stack[4095]),clone_flag,(void*)&arg);
}
分析:
声明变量 *arg,在循环中 把 arg=i; 调用 clone时, 传入参数 &arg;
虽然 arg每次循环后 ,值不一样,但是 传入的参数&arg 即arg的地址没有变化,所以 作者原意 要创建两个 生产者和两个消费者的线程, 在实际运行会发现 结果只能创建出一个生产者和一个消费者。
修改后代码为:
int clone_flag,*arg, args[2] = {0, 1},retval;
char *stack;
clone_flag = CLONE_VM|CLONE_SIGHAND|CLONE_FS|CLONE_FILES;
int i;
for(i=0;i<2;i++)
{
arg = &args[i];
stack=(char*)malloc(4096);
retval = clone((void*)producer,&(stack[4095]),clone_flag,(void*)arg);
stack=(char*)malloc(4096);
retval = clone((void*)consumer,&(stack[4095]),clone_flag,(void*)arg);
}
完整代码如下:
#include "sched.h"
#include "pthread.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "semaphore.h"
int producer(void *args);
int consumer(void *args);
pthread_mutex_t mutex;
sem_t product;
sem_t warehouse;
char buffer[8][4];
int bp=0;
int main(int argc,char **argv)
{
pthread_mutex_init(&mutex,NULL);
sem_init(&product,0,0);
sem_init(&warehouse,0,8);
int clone_flag,*arg, args[2] = {0, 1},retval;
char *stack;
clone_flag = CLONE_VM|CLONE_SIGHAND|CLONE_FS|CLONE_FILES;
int i;
for(i=0;i<2;i++)
{
arg = &args[i];
stack=(char*)malloc(4096);
retval = clone((void*)producer,&(stack[4095]),clone_flag,(void*)arg);
stack=(char*)malloc(4096);
retval = clone((void*)consumer,&(stack[4095]),clone_flag,(void*)arg);
}
exit(1);
}
int producer(void *args)
{
int id=*((int*)args);
int i;
for(i=0;i<10;i++)
{
sleep(i+1);
sem_wait(&warehouse);
pthread_mutex_lock(&mutex);
if(id==0)
strcpy(buffer[bp],"aaa\0");
else
strcpy(buffer[bp],"bbb\0");
bp++;
printf("producer %d produce %s in %d\n",id,buffer[bp-1],bp-1);
pthread_mutex_unlock(&mutex);
sem_post(&product);
}
printf("producer %d is over!\n",id);
}
int consumer(void *args)
{
int id=*((int*)args);
int i;
for(i=0;i<10;i++)
{
sleep(10-i);
sem_wait(&product);
pthread_mutex_lock(&mutex);
bp--;
printf("consumer %d get %s in %d\n",id,buffer[bp],bp);
strcpy(buffer[bp],"zzz\0");
pthread_mutex_unlock(&mutex);
sem_post(&warehouse);
}
printf("consumer %d is over!\n",id);
}