编写生产者和消费者程序,要求: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文件和上述源代码放到同一个文件目录下,再执行上述代码。

  • 3
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值