一、实验目的及要求

“生产者消费者”问题是一个著名的同时性编程问题的集合。通过编写经典的”生产者消费者”问题的实验,读者可以进一步熟悉 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>
#define MYFIFO        "myfifo"    /*缓冲区有名管道的名字*/
#define BUFFER_SIZE        3        /*缓冲区的单元数*/
#define UNIT_SIZE    6            /*每个单元的字节大小*/
#define RUN_TIME    30            /*运行时间*/
#define DELAY_TIME_LEVELS    5.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)
{unsigned char 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);
}//主函数int main()
{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);  /*所有打开该文件的进程都结束时文件被删除*/return 0;
}

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

实验结果:


实验代码:

 #include <stdio.h>#include <pthread.h>#define BUFFER_SIZE 4#define OVER (-1)struct producers//定义生产者条件变量结构{int buffer[BUFFER_SIZE];pthread_mutex_t lock;int readpos, writepos;pthread_cond_t notempty;pthread_cond_t notfull;};//初始化缓冲区void init(struct producers *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;}//在缓冲区存放一个整数void put(struct producers *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);}int get(struct producers *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;}struct producers buffer;void *producer(void *data){int n;for(n=0;n<10;n++){printf("Producer : %d-->\n",n);put(&buffer,n);}put(&buffer,OVER);return NULL;}void *consumer(void *data){int d;while(1){d=get(&buffer);if(d==OVER) break;printf("Consumer: --> %d\n",d);}return NULL;}int main(){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);return 0;}

特别注意:如果运行时出现这种情况:

说明此时你并没有权限,上个权限就好了(sudo -s)

【上知乎搜:乘风与你渡晚舟】
csdn网站与知乎网站同作者

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

  1. Linux相关——linux操作系统之生产者与消费者同步问题

    #include<stdio.h> #include<linux/sem.h> #include<linux/shm.h> #include<unistd.h ...

  2. 实验报告Linux操作系统基本命令,linux操作系统实验报告全部.doc

    linux操作系统实验报告全部 计算机操作系统 实验报告 学 号:姓 名:提交日期:2014.12.15成 绩: 东北大学秦皇岛分校 [实验题目]熟悉Linux/UNIX操作系统[实验目的]1.熟悉L ...

  3. linux系统实训总结报告,Linux操作系统实验报告.doc

    Linux操作系统实验报告.doc LINUX 操作系统实验报告课 程 Linux 操作系统 专 业 学 号 姓 名 指导教师 XXXXX 系20 年 月 日实验一 LINUX 基本命令实验目的1.掌 ...

  4. linux操作系统实验教程费翔林,实验一操作系统接口实验.doc

    实验一 操作系统交互式接口使用 (一)实验环境:linux 用户名和密码:user (二)实验的目的:了解linux的各种操作命令的使用 (三)实验要求 1.按照指导书完成各种命令的使用 2.写实验报 ...

  5. Linux基于bash命令实验报告,Linux操作系统实验报告1

    Linux操作系统实验报告1 下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览.不比对内容而直接下载带来的问题本站不予受理. 2.下载的文档,不会出现我们的网址水印. 3.该文档所 ...

  6. linux系统使用实验报告操作系统,linux操作系统实验报告1.doc

    linux操作系统实验报告1.doc 实验LINUXSHELL基本命令使用实验目的熟悉LINUX操作系统环境,掌握LINUX的基本命令.实验提示1.LINUX命令行的语法结构COMMANDOPTION ...

  7. 操作系统实验 生产者消费者问题详解

    操作系统课程设计 生产者消费者实验报告 一.实验目的 加深对进程概念的理解,明确进程与程序的区别. 认识并发执行的本质. 理解和掌握Linux和Windows进程通信系统调用的功能,通过实验和学习,提 ...

  8. 实验四linux操作系统实验报告(1),操作系统实验报告

    一. 实验目的及实验环境 (一) 实验环境 Linux 操作系统 (二)实验目的 实验1 掌握Linux基本命令 和开发环境 掌握常用的Linux shell命令: 掌握编辑环境VIM: 掌握编译环境 ...

  9. linux文件目录操作实验报告,Linux操作系统实验4文件和目录操作

    <Linux操作系统>课程实验报告 实验4 文件和目录操作 一.实验目的 1.理解Linux文件系统的结构和目录组织方式: 2.掌握Linux常用目录和文件命令的使用. 二.实验内容与要求 ...

最新文章

  1. centos安装 TA-Lib
  2. kotlin 查找id_Kotlin程序查找等边三角形的区域
  3. 关于Chrome出现Provisional headers are shown无法正常访问的解决方案(其他firefox,360, IE访问正常) (转)...
  4. ubuntu系统安装python hello_ubuntu 下python安装及hello world
  5. POJ2987 Firing 最大权闭合图
  6. 习题3.8 符号配对 (20 分)
  7. 《数学分析(上)》重要概念复习
  8. graphpad如何换柱状图与折线图能否混合一起_Graphpad Prism 绘制柱状图与散点图共存图...
  9. 数据结构实验之二叉树二:遍历二叉树(中序后序遍历)
  10. [单片机框架][bsp层][AT32F415][bsp_adc] adc配置和使用
  11. 抽象工厂模式---游戏等级
  12. 推特难民涌入「长毛象」!这个小众社交平台一夜爆红
  13. sim7600ce使用MQTT协议总结
  14. 360浏览器中页面打开如何默认极速模式
  15. Android数据库备份和恢复
  16. 线性表的应用——多项式的计算
  17. 几种Java常用序列化框架的选型与对比
  18. TM1637芯片使用(I2C总线协议学习),含完整程序
  19. Ubuntu中Kdevelop的安装和使用
  20. php实现分时线图,史上最全分时图买卖点图解(转发收藏)!

热门文章

  1. 【龙芯1B】:DS18B20测温例程
  2. HT1621段码液晶屏
  3. Selenium全屏截图,使用PIL拼接滚动截图
  4. 用python绘制多组箱线图、柱状图、簇状图
  5. 基于MATLAB的机动车车牌自动识别系统
  6. drupal7模板命名机制/规则
  7. 网络安全通识全解|第9期 揭秘黑客的常用攻击手段
  8. 删除cookie,domain的设置
  9. 火狐启用falsh_如何在Firefox中启用暗模式
  10. Linux调试器工作原理——基础篇