0


Linux操作系统实验:生产者和消费者问题

一、实验目的及要求

“生产者消费者”问题是一个著名的同时性编程问题的集合。通过编写经典的”生产者消费者”问题的实验,读者可以进一步熟悉 Linux 中多线程编程,并且掌握用信号量处理线程间的同步互斥问题。

二、实验仪器设备与软件环境

VMware Workstation Pro

三、实验过程及实验结果分析

“生产者消费者”问题描述如下。 有一个有限缓冲区和两个线程:生产者和消费者。他们分别把产品放入缓冲区和从缓冲区中 拿走产品。当一个生产者在缓冲区满时必须等待,当一个消费者在缓冲区空时也必须等待。 它们之间的关系如下图所示:
在这里插入图片描述

这里要求用有名管道来模拟有限缓冲区,用信号量来解决生产者消费者问题中的同步和互斥问题。

(1) 使用信号量解决

实验结果:
在这里插入图片描述
实验代码:

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<fcntl.h>#include<errno.h>#include<pthread.h>#include<semaphore.h>#include<sys/ipc.h>#include<sys/types.h>#include<sys/stat.h>#defineMYFIFO"myfifo"/*缓冲区有名管道的名字*/#defineBUFFER_SIZE3/*缓冲区的单元数*/#defineUNIT_SIZE6/*每个单元的字节大小*/#defineRUN_TIME30/*运行时间*/#defineDELAY_TIME_LEVELS5.0/*周期的最大值*/int fd;/*管道描述符*/time_t end_time;/*存放线程的起始时间*/sem_t mutex,full,avail;/*信号量描述符*//*生产者线程*/void*producer(void*arg){int real_write;/*实际写入字节数*/int delay_time=0;/*time(NULL)返回从公元1970年1月1日的UTC时间0时0分0秒算起
 到现在所经过的秒数,while()的意思就是说如果在执行生产者线程的
 那一刻没有超过其结束时间,那么则执行*/while(time(NULL)<end_time){
        delay_time=(int)(rand()*DELAY_TIME_LEVELS/(RAND_MAX)/2.0)+1;sleep(delay_time);/*P操作信号量 avail 和 mutex */sem_wait(&avail);sem_wait(&mutex);printf("\nProducer:delay=%d\n",delay_time);/*生产者写入数据*/if((real_write=write(fd,"hello",UNIT_SIZE))==-1){/*这个errno=EAGAIN表示的是你的write本来是非阻塞情况,现在没有数
 据可读,这个时候就会置全局变量errno为EAGINA,表示可以再次进行读
 操作;如果是阻塞情况,那么被中断的话,errno=EINTR*/if(errno==EAGAIN){printf("The FIFO has not been read yet.Please try later\n");}}else{printf("Write %d to the FIFO\n",real_write);}/*V操作信号量full和mutex*/sem_post(&full);sem_post(&mutex);}pthread_exit(NULL);}/*消费者线程*/void*customer(void*arg){unsignedchar read_buffer[UNIT_SIZE];int real_read;int delay_time;while(time(NULL)<end_time){
        delay_time=(int)(rand()*DELAY_TIME_LEVELS/(RAND_MAX))+1;sleep(delay_time);/*P操作信号量full和mutex*/sem_wait(&full);sem_wait(&mutex);memset(read_buffer,0,UNIT_SIZE);printf("\nCustomer:delay=%d\n",delay_time);if((real_read=read(fd,read_buffer,UNIT_SIZE))==-1){if(errno==EAGAIN){printf("No data yet\n");}}printf("Read %s from FIFO\n",read_buffer);/*V操作信号量avail和mutex*/sem_post(&avail);sem_post(&mutex);}pthread_exit(NULL);}//主函数intmain(){pthread_t thrd_pro_id,thrd_cus_id;pthread_t mon_th_id;int ret;srand(time(NULL));/*随机数发生器初始化*/
    end_time=time(NULL)+RUN_TIME;/*创建有名管道*/if((mkfifo(MYFIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST)){printf("Cannot create fifo\n");return errno;}/*打开管道*/
    fd=open(MYFIFO,O_RDWR,0666);if(fd==-1){printf("Open fifo error\n");return fd;}/*初始化互斥信号量为1*/
    ret=sem_init(&mutex,0,1);/*初始化avail信号量为N*/
    ret+=sem_init(&avail,0,BUFFER_SIZE);/*初始化full信号量为0*/
    ret+=sem_init(&full,0,0);if(ret!=0){printf("Any semaphore initialization failed\n");return ret;}/*创建两个进程*/
    ret=pthread_create(&thrd_pro_id,NULL,producer,NULL);if(ret!=0){printf("Create producer thread error\n");return ret;}
    ret=pthread_create(&thrd_cus_id,NULL,customer,NULL);if(ret!=0){printf("Create producer thread error\n");return ret;}pthread_join(thrd_pro_id,NULL);pthread_join(thrd_cus_id,NULL);close(fd);//    unlink(MYFIFO);  /*所有打开该文件的进程都结束时文件被删除*/return0;}

(2)思考使用条件变量解决

实验结果:
在这里插入图片描述
在这里插入图片描述
实验代码:

#include<stdio.h>#include<pthread.h>#defineBUFFER_SIZE4#defineOVER(-1)structproducers//定义生产者条件变量结构{int buffer[BUFFER_SIZE];pthread_mutex_t lock;int readpos, writepos;pthread_cond_t notempty;pthread_cond_t notfull;};//初始化缓冲区voidinit(structproducers*b){pthread_mutex_init(&b->lock,NULL);pthread_cond_init(&b->notempty,NULL);pthread_cond_init(&b->notfull,NULL);
     b->readpos=0;
     b->writepos=0;}//在缓冲区存放一个整数voidput(structproducers*b,int data){pthread_mutex_lock(&b->lock);//当缓冲区为满时等待while((b->writepos+1)%BUFFER_SIZE==b->readpos){pthread_cond_wait(&b->notfull,&b->lock);}
     b->buffer[b->writepos]=data;
     b->writepos++;if(b->writepos>=BUFFER_SIZE) b->writepos=0;//发送当前缓冲区中有数据的信号pthread_cond_signal(&b->notempty);pthread_mutex_unlock(&b->lock);}intget(structproducers*b){int data;pthread_mutex_lock(&b->lock);while(b->writepos==b->readpos){pthread_cond_wait(&b->notempty,&b->lock);}
     data=b->buffer[b->readpos];
     b->readpos++;if(b->readpos>=BUFFER_SIZE) b->readpos=0;pthread_cond_signal(&b->notfull);pthread_mutex_unlock(&b->lock);return data;}structproducers buffer;void*producer(void*data){int n;for(n=0;n<10;n++){printf("Producer : %d-->\n",n);put(&buffer,n);}put(&buffer,OVER);returnNULL;}void*consumer(void*data){int d;while(1){
     d=get(&buffer);if(d==OVER)break;printf("Consumer: --> %d\n",d);}returnNULL;}intmain(){pthread_t tha,thb;void*retval;init(&buffer);pthread_create(&tha,NULL,producer,0);pthread_create(&thb,NULL,consumer,0);pthread_join(tha,&retval);pthread_join(thb,&retval);return0;}

特别注意:如果运行时出现这种情况:
在这里插入图片描述
说明此时你并没有权限,上个权限就好了(sudo -s)
在这里插入图片描述
【上知乎搜:乘风与你渡晚舟】
csdn网站与知乎网站同作者

标签: linux 运维 服务器

本文转载自: https://blog.csdn.net/m0_52503037/article/details/130197757
版权归原作者 Futurist_ljl 所有, 如有侵权,请联系我们删除。

“Linux操作系统实验:生产者和消费者问题”的评论:

还没有评论