编写生产者和消费者程序,要求:1) 生产者和消费者两个程序,共用一个仓库,仓库是一个普通文件(/tmp/store),容量为100个字节;

这篇具有很好参考价值的文章主要介绍了编写生产者和消费者程序,要求:1) 生产者和消费者两个程序,共用一个仓库,仓库是一个普通文件(/tmp/store),容量为100个字节;。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

编写生产者和消费者程序,要求:

1)    生产者和消费者两个程序,共用一个仓库,仓库是一个普通文件(/tmp/store),容量为100个字节;

2)    生产者生产资源放进仓库,消费者则从仓库中消费资源;资源为数字字符“1、2、3、4、5、6、7、8、9、0”,一个资源就是一个数字,10个数字循环生成;

3)    生产者创建仓库(/tmp/store),间隔1s生产一个资源,当仓库满了(资源数量达到100个)的时候,生产者不能继续生产;消费者间隔2s消费一个资源,当仓库为空的时候,消费者不能继续消费;

4)    消费者每次消费1个资源,首先打印出消耗之前仓库中的资源数量和空位的数量,然后打印出消耗之后仓库中的资源数量和空位的数量,并打印出所消耗的资源内容;

5)    生产者每次生产1个资源,先打印出生产之前仓库中的资源数量和空位的数量,然后打印出生产之后仓库中的资源数量和空位的数量,并打印出所生产的资源内容。

6)    消费者消费资源后需要把已经消费的资源从仓库里删除;

7)    用信号量实现进程的同步和互斥。

【提示】题目有多种解决方案,可以用1个或多个信号量,或者使用其他合适的方法。

源代码如下:

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include<sys/ipc.h>
#include<sys/sem.h>
 /* 为了后期方便实用信号量,引入该文件*/
#include"sem_com.c"
/* 这个是源文件名*/
#define SRC_FILE_NAME "src_file" 
 /* 这个是目标文件名*/
#define DEST_FILE_NAME "dest_file"
#define OFFSET 1 

int src_file,tmp_file;
char consuming()
{char item;
char buff;
int real_read_len;
src_file = open(SRC_FILE_NAME, O_RDWR);
tmp_file = open(DEST_FILE_NAME, O_RDWR|O_CREAT|O_TRUNC,666);
if (src_file< 0 )
{
printf("文件打开错误\n");
exit(1);
}
if (tmp_file< 0 )
{
printf("临时文件错误\n");
exit(1);
}
read(src_file,&item,sizeof(char));
while((real_read_len = read(src_file,&buff,sizeof(buff))) >0)
{
write(tmp_file,&buff,real_read_len);
}
close(src_file);
close(tmp_file);

src_file = open(SRC_FILE_NAME, O_RDWR|O_TRUNC);
tmp_file = open(DEST_FILE_NAME, O_RDWR);

while((real_read_len = read(tmp_file,&buff,sizeof(buff))) >0)
{
write(src_file,&buff,real_read_len);
}
close(src_file);
close(tmp_file);
return item;
}
int main()
{
pid_t result;
/* 定义信号量集的ID号*/
int empty,full,mutex,mutex1; 
 /* 如果信号量集已经存在,就删除已经存在的并重新创建一个信号量集,防止多次运行导致的信号量紊乱*/
if(full=semget(ftok("/", 1), 1, 0666))  
{
del_sem(full);
full= semget(ftok("/", 1), 1, 0666|IPC_CREAT); /* 创建一个信号量集*/
}
else
{
full= semget(ftok("/", 1), 1, 0666|IPC_CREAT); /* 创建一个信号量集*/
}
if(empty= semget(ftok("/", 2), 1, 0666))
{
del_sem(empty);
empty= semget(ftok("/", 2), 1, 0666|IPC_CREAT); /* 创建一个信号量集*/
}
else
{
empty= semget(ftok("/", 2), 1, 0666|IPC_CREAT); /* 创建一个信号量集*/
}
if(mutex= semget(ftok("/", 3), 1, 0666))
{
del_sem(mutex);
mutex= semget(ftok("/", 3), 1, 0666|IPC_CREAT); /* 创建一个信号量集*/
}
else
{
mutex= semget(ftok("/", 3), 1, 0666|IPC_CREAT); /* 创建一个信号量集*/
}
if(mutex1= semget(ftok("/", 4), 1, 0666))
{
del_sem(mutex1);
mutex1= semget(ftok("/", 4), 1, 0666|IPC_CREAT); /* 创建一个信号量集*/
}
else
{
mutex1= semget(ftok("/", 4), 1, 0666|IPC_CREAT); /* 创建一个信号量集*/
}
init_sem(full,0,0); /* 初始化信号量*/
init_sem(empty,0,100); /* 初始化信号量*/
init_sem(mutex,0,1); /* 初始化信号量*/
init_sem(mutex1,0,1); /* 初始化信号量,mutex1是为了让生产者和消费者中各自的三句话不分开*/
/*调用fork()函数创建子进程*/
result = fork();
if(result == -1)
{
perror("Fork\n");
}
else if (result == 0) /*返回值为0 代表子进程,这里用作生产者进程*/
{
src_file = open(SRC_FILE_NAME, O_RDWR|O_CREAT|O_APPEND,666);
while(1)
{
char i='0';
while(i<='9')
{
if(semctl(empty,0,GETVAL,NULL)>0)
{
sem_p(mutex1,0);
printf("生产前:已经存在: %d 空余: %d\n\n",semctl(full,0,GETVAL,NULL),semctl(empty,0,GETVAL,NULL));
sem_p(empty,0);
sem_p(mutex,0);
write(src_file,&i,sizeof(i));
printf("生产者:生产的产品编号是: %c\n\n",i);
sem_v(mutex,0);
sem_v(full,0);
printf("生产后:目前存在:full %d 空余: %d\n\n",semctl(full,0,GETVAL,NULL),semctl(empty,0,GETVAL,NULL));
sem_v(mutex1,0);
i=i+1;
}
else
{
printf("**********************\n");
printf("仓库已经满了!\n\n");
}
/*线程阻塞1*/
sleep(1);
}
}
}
else/*返回值大于0 代表父进程,这里用作消费者进程*/
{
char item;
while(1)
{
if(semctl(full,0,GETVAL,NULL)>0)
{
sem_p(mutex1,0);
printf("消费前:已经存在: %d 空余: %d\n\n",semctl(full,0,GETVAL,NULL),semctl(empty,0,GETVAL,NULL));
sem_p(full,0);
sem_p(mutex,0);
item=consuming();
printf("消费者消费的产品号是: %c\n\n",item);
sem_v(mutex,0);
sem_v(empty,0);
printf("消费后:目前存在: %d 空余 %d\n\n",semctl(full,0,GETVAL,NULL),semctl(empty,0,GETVAL,NULL));
sem_v(mutex1,0);
}
else
{
printf("**********************\n");
printf("仓库目前空了!\n\n");
}
/*线程阻塞2*/
sleep(2);
}
}
}

需要注意的是:这里为了后期方便实用信号量,使用 #include"sem_com.c" 引入了sem_com.c文件

sem_com.c文件的源代码是:

/* sem_com.c */
/* 信号量初始化(赋值)函数*/
int init_sem(int sem_id, int n,int init_value)
{
union semun{
int val;
struct semid_ds *buf;
unsigned short *array;
};
union semun sem_union;
sem_union.val = init_value;   /* init_value 为初始值 */
if (semctl(sem_id, n, SETVAL, sem_union) == -1)
{
perror("Initialize semaphore");
return -1;
}
return 0;
}

/* 从系统中删除信号量集的函数 */
int del_sem(int sem_id)
{
if (semctl(sem_id, 0, IPC_RMID,NULL) == -1)
{
perror("Delete semaphore");
return -1;
}
}

/* P 操作函数 */
int sem_p(int sem_id,int n)
{
struct sembuf sem_b;
sem_b.sem_num = n; /* 单个信号量的编号如果为0,即信号量集中的第一个信号量 */
sem_b.sem_op = -1; /* 表示P 操作 */
sem_b.sem_flg = SEM_UNDO; /* 系统自动释放将会在系统中残留的信号量*/
if (semop(sem_id, &sem_b, 1) == -1)
{
perror("P operation");
return -1;
}
return 0;
}

/* V 操作函数*/
int sem_v(int sem_id,int n)
{
struct sembuf sem_b;
sem_b.sem_num = n; /* 单个信号量的编号应该为0 */
sem_b.sem_op = 1; /* 表示V 操作 */
sem_b.sem_flg = SEM_UNDO; /* 系统自动释放将会在系统中残留的信号量*/
if (semop(sem_id, &sem_b, 1) == -1)
{
perror("V operation");
return -1;
}
return 0;
}

需要把这个sem_com.c文件和上述源代码放到同一个文件目录下,再执行上述代码。文章来源地址https://www.toymoban.com/news/detail-751594.html

到了这里,关于编写生产者和消费者程序,要求:1) 生产者和消费者两个程序,共用一个仓库,仓库是一个普通文件(/tmp/store),容量为100个字节;的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • rabbitmq消费者与生产者

    在第一次学习rabbitmq的时候,遇到了许多不懂得 第一步导包 第二步新增生产者 在这里中: connectionFactory.setVirtualHost(\\\"my_vhost\\\");//填写自己的队列名称,如果你的为”/“则填写\\\'\\\'/\\\'\\\' 第三步新增消费者 消息获取成功 注意如果你用的云服务器需要打开这两个端口 5672 15672 如果你使

    2024年02月11日
    浏览(33)
  • 多线程之生产者消费者

    目的是回顾多线程的几个api 多生产者+多消费者+共享池

    2024年02月07日
    浏览(30)
  • 线程同步--生产者消费者模型

    条件变量是 线程间共享的全局变量 ,线程间可以通过条件变量进行同步控制 条件变量的使用必须依赖于互斥锁以确保线程安全,线程申请了互斥锁后,可以调用特定函数 进入条件变量等待队列(同时释放互斥锁) ,其他线程则可以通过条件变量在特定的条件下唤醒该线程( 唤醒后线

    2024年01月19日
    浏览(24)
  • linux:生产者消费者模型

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

    2024年04月15日
    浏览(32)
  • kafka生产者消费者练习

    需求:写一个生产者,不断的去生产用户行为数据,写入到kafka的一个topic中 生产的数据格式: 造数据 {“guid”:1,“eventId”:“pageview”,“timestamp”:1637868346789} isNew = 1 {“guid”:1,“eventId”:“addcard”,“timestamp”:1637868347625} isNew = 0 {“guid”:2,“eventId”:“collect”,“timestamp”

    2024年02月08日
    浏览(30)
  • LabVIEW建立生产者消费者

    LabVIEW建立生产者消费者 生产者/消费者设计模式由并行循环组成,这些循环分为两类:生产者循环和消费者循环。生产者循环和消费者循环间的通信可以使用队列或通道连线来实现。 队列 LabVIEW内置的队列操作VI可在函数选板数据通信队列操作( Functions Data Communication  Que

    2024年02月07日
    浏览(26)
  • Linux——生产者消费者模型

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

    2024年02月08日
    浏览(31)
  • 【JavaEE】生产者消费者模式

    作者主页: paper jie_博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文于《JavaEE》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将基础知识一网打尽,希望可以帮到读者们哦。 其他专栏:《MySQL》《C语言》

    2024年02月05日
    浏览(28)
  • python rocketmq生产者消费者

    安装依赖包 生产者 需要注意的是假如你用的java SDK 需要只是UNinname 我们可以看到下列代码设置了tag以及key,在页面可以根据key查找消息 消费方式PullConsumer(全部消费)(可重复消费) 消费方式PushConsumer(即时消费)(不可重复消费) 生产者发送消息选择队列,以及设置顺

    2024年02月14日
    浏览(25)
  • 生产者消费者模型 C++ 版

    网上一般教程是使用std::queue,定义消费者 Consumer ,定义Producter类,在main函数里面加锁保证线程安全。 本片文章,实现一个线程安全的队列 threadsafe_queue,只在队列内部加锁。如此可适配,多生产者多消费者的场景 Consumer 头文件 cpp文件 运行结果如下: 优先队列做缓存 头文件

    2024年02月13日
    浏览(23)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包