操作系统实验 进程与线程——Linux进程与线程通信

操作系统实验 进程与线程——Linux进程与线程通信


(一) 实验目的
深刻理解线程和进程的概念,掌握线程与进程在组成成分上的差别,以及与其相适应的通讯方式和应用目标
(二) 实验内容
以Linux系统进程和线程机制为背景,掌握fork()和clone()系统调用的形式和功能,以及与其相适应的高级通讯方式。由fork派生的子进程之间通过pipe通讯,由clone创建的线程之间通过共享内存通讯,对于后者需要考虑互斥问题。
以生产者/消费者问题为例,通过实验理解fork()和clone()两个系统调用的区别。程序要求能够创建4个进程或线程,其中包括两个生产者和两个消费者,生产者和消费者之间能够传递数据。
(三) 实验准备
fork系统调用
clone系统调用
pipe系统调用
sem_wait(&s)和sem_post(&s)
pthread_mutex_lock(&mutex)和pthread_mutex_unlock(&mutex)
(四) 实验设计
用pipe()创建一个管道文件,然后用fork()创建两个生产进程和两个消费进程,它们之间通过pipe()传递信息。
用clone()创建四个轻进程(线程),用参数指明共享内存等资源,通过共享内存模拟生产消费问题,利用pthread_mutex_lock(), pthread_mutex_unlock()等函数实现对共享存储区访问的互斥。
实验代码:
fork系统调用实验代码:

#include "sys/types.h"
#include "sys/file.h"
#include "unistd.h"
char r_buf[4];  //读缓冲
char w_buf[4];  //写缓冲
int pipe_fd[2];
pid_t pid1, pid2, pid3, pid4;
int producer(int id);
int consumer(int id);
int main(int argc,char **argv)
{  
if(pipe(pipe_fd)<0)
{
        printf("pipe create error \n");
        exit(-1);
}
else
{
printf("pipe is created successfully!\n");
if((pid1=fork())==0)
      producer(1);
if((pid2=fork())==0)
      producer(2);
if((pid3=fork())==0)
      consumer(1);
if((pid4=fork())==0)
      consumer(2);
    }
close(pipe_fd[0]);  //需要加上这两句
close(pipe_fd[1]);  //否这会有读者或者写者永远等待
    int i,pid,status;
for(i=0;i<4;i++)
 pid=wait(&status);  
   exit(0);
}

int producer(int id)
{
    printf("producer %d is running!\n",id);
    close(pipe_fd[0]);
    int i=0;
    for(i=1;i<10;i++)
    {
        sleep(3);
        if(id==1) //生产者1
             strcpy(w_buf,"aaa\0");
        else  //生产者2
             strcpy(w_buf,"bbb\0");
        if(write(pipe_fd[1],w_buf,4)==-1)
            printf("write to pipe error\n");    
    }
    close(pipe_fd[1]);
    printf("producer %d is over!\n",id);
    exit(id);
}
int consumer(int id)
{
    close(pipe_fd[1]); 
    printf("producer %d is running!\n",id);
    if (id==1)  //消费者1
strcpy(w_buf,"ccc\0");
    else  //消费者2
strcpy(w_buf,"ddd\0");
    while(1)
    {
         sleep(1);
         strcpy(r_buf,"eee\0");
         if(read(pipe_fd[0],r_buf,4)==0)
             break;     
         printf("consumer %d get %s, while the w_buf is %s\n",id,r_buf,w_buf);
    }
    close(pipe_fd[0]);
    printf("consumer %d is over!\n", id);
    exit(id);
}

编译:gcc fork.c -o fork.out 源文件:fork.c
运行:./fork.out 编译后生成文件:fork.out
结果:

操作系统实验 进程与线程——Linux进程与线程通信_第1张图片
clone系统调用实验代码:

#include "sched.h"
#include "pthread.h"
#include "stdio.h"
#include "stdlib.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;
main(int argc,char** argv)
{
  pthread_mutex_init(&mutex,NULL);
   sem_init(&product,0,0);
    sem_init(&warehouse,0,8);
   int clone_flag,arg,retval;
    char *stack;
    clone_flag=CLONE_VM|CLONE_SIGHAND|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);
    //usleep(1000);
    usleep(1);
    }
    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+1);
        strcpy(buffer[bp],"zzz\0");
        pthread_mutex_unlock(&mutex);
        sem_post(&warehouse);
    }
    printf("consumer%d is over!\n",id);
}

编译:gcc pthread clone.c -o clone.out 源文件clone.c
运行:./clone.out 编译后文件:clone.out
结果:(太长只截部分)
操作系统实验 进程与线程——Linux进程与线程通信_第2张图片

你可能感兴趣的:(其他)