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

这篇具有很好参考价值的文章主要介绍了Linux操作系统实验:生产者和消费者问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、实验目的及要求

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

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

VMware Workstation Pro

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

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

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

(1) 使用信号量解决

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

#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)思考使用条件变量解决

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

 #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;
 }

特别注意:如果运行时出现这种情况:
Linux操作系统实验:生产者和消费者问题
说明此时你并没有权限,上个权限就好了(sudo -s)
Linux操作系统实验:生产者和消费者问题
【上知乎搜:乘风与你渡晚舟】
csdn网站与知乎网站同作者文章来源地址https://www.toymoban.com/news/detail-455719.html

到了这里,关于Linux操作系统实验:生产者和消费者问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Linux——生产者消费者模型

    目录 一.为何要使用生产者消费者模型  二.生产者消费者模型优点  三.基于BlockingQueue的生产者消费者模型 1.BlockingQueue——阻塞队列 2.实现代码  四.POSIX信号量 五.基于环形队列的生产消费模型 生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者

    2024年02月08日
    浏览(43)
  • linux:生产者消费者模型

    个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》《C++》《Linux》 本文是对于生产者消费者模型的知识总结 生产者消费者模型就是通过一个容器来解决生产者消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而是通过之间的容器来进行通讯,所以生产者

    2024年04月15日
    浏览(41)
  • 【Linux】深入理解生产者消费者模型

    生产者 - 消费者模型 Producer-consumer problem 是一个非常经典的多线程并发协作的模型,在分布式系统里非常常见。 在多线程开发中,如果生产者生产数据的速度很快,而消费者消费数据的速度很慢,那么生产者就必须等待消费者消费完了数据才能够继续生产数据,同理如果消费

    2024年02月06日
    浏览(36)
  • 【Linux】线程安全-生产者消费者模型

    1个线程安全的队列:只要保证先进先出特性的数据结构都可以称为队列 这个队列要保证互斥(就是保证当前只有一个线程对队列进行操作,其他线程不可以同时来操作),还要保证同步,当生产者将队列中填充满了之后要通知消费者来进行消费,消费者消费之后通知生产者

    2024年02月10日
    浏览(46)
  • Linux——生产者消费者模型和信号量

    目录 ​​​​​​​ 基于BlockingQueue的生产者消费者模型 概念 条件变量的第二个参数的作用  锁的作用 生产者消费者模型的高效性 生产者而言,向blockqueue里面放置任务 消费者而言,从blockqueue里面拿取任务: 总结 完整代码(不含存储数据的线程) 完整代码(含存储线程)  信

    2024年02月07日
    浏览(40)
  • 【Linux】cp问题,生产者消费者问题代码实现

    生产者消费者模式就是通过一个容器 来解决生产者和消费者的强耦合问题 。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞

    2024年02月04日
    浏览(34)
  • Linux安装Kafka,创建topic、生产者、消费者

    1.创建安装目录/usr/local/kafka mkdir /usr/local/kafka 2.进入安装包目录 cd /usr/local/kafka  3.下载安装包 wget https://downloads.apache.org/kafka/3.3.1/kafka_2.12-3.3.1.tgz 4.解压安装包 tar -zxvf kafka_2.12-3.3.1.tgz 5.进入cd kafka_2.12-3.3.1目录 cd kafka_2.12-3.3.1/ 6.修改zookeeper配置 cat ./config/zookeeper.properties | grep

    2023年04月17日
    浏览(46)
  • 【linux】线程同步+基于BlockingQueue的生产者消费者模型

    喜欢的点赞,收藏,关注一下把! 在线程互斥写了一份抢票的代码,我们发现虽然加锁解决了抢到负数票的问题,但是一直都是一个线程在抢票,它错了吗,它没错但是不合理。那我们应该如何安全合理的抢票呢? 讲个小故事。 假设学校有一个VIP学霸自习室,这个自习室有

    2024年02月03日
    浏览(98)
  • 【Linux】生产者消费者模型代码实现和信号量

    一定要先理解生产者消费者模型的原理~ 文章目录 一、生产者消费者模型实现代码 二、信号量 1.基于环形队列的生产者消费者模型 总结 下面我们实现基于阻塞队列的生产消费模型: 在多线程编程中阻塞队列 (Blocking Queue) 是一种常用于实现生产者和消费者模型的数据结构。其

    2024年02月11日
    浏览(37)
  • 【Linux】基于环形队列的生产者消费者模型的实现

    文章目录 前言 一、基于环形队列的生产者消费者模型的实现 上一篇文章我们讲了信号量的几个接口和基于环形队列的生产者消费者模型,下面我们就快速来实现。 首先我们创建三个文件,分别是makefile,RingQueue.hpp,以及main.cc。我们先简单搭建一下环形队列的框架: 首先我们

    2024年02月11日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包