Linux信号量之生产者与消费者

设计一个程序,程序中有一个生产者进程两个消费者进程。生产者产生1~20的20个数。两个消费者从共享内存中取数。

首先分析题目
生产者和消费者之间存在着协同关系。而两个消费者要满足互斥。所以我们需要三个信号量,一个用来控制互斥,两个用来控制协同

我们知道前一种非常简单,实现互斥就是用一把公用的锁把临界区锁住

而协同关系则复杂一些。我们知道信号量的值就是进程可以使用的资源的个数。对于生产者来说,资源就是空的存储区。对于消费者来说,资源就是存有数据的存储区。所以用两个信号量,一个是empty,一个是full。empty初始值为1代表一开始内存是空闲的,full初始值为0表示没有数据可用。生产者在生产之前他会将empty变成0,然后生产之后他又把full变成1。empty避免了其他生产者在同一块内存上生产数据。而消费者在消费之前就把full变成0,消费之后又把empty变成1。这样两两协同,便实现了协同和互斥的关系。

接下来贴代码

包含头文件并定义所需全局变量:
#include <iostream>
#include <sys/types.h>
#include <sys/sem.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <errno.h>
#include <time.h>
#include<unistd.h>
using namespace std;
        struct sembuf P,V;
        union senum{
            int val;
            struct semid_ds *buf; 
           unsigned short *array;
        }arc;

封装函数:
void sem_init()//初始化信号量的运行环境
{
P.sem_num= 0;
P.sem_op =-1;//信号量在操作时-1
P.sem_flg=SEM_UNDO;
V.sem_num= 0;
V.sem_op =1;//信号量在操作时+1
V.sem_flg=SEM_UNDO;
cout<<"Semaphore Initiate Successfully"<<endl;
}

void v(int sem_id)//v操作
{
    semop(sem_id,&V,1);
}
void p(int sem_id)//p操作
{
    semop(sem_id,&P,1);
}
void sem_crea(int &sem_id,int val)//用val来给信号量赋初值
{
    sem_id=semget(IPC_PRIVATE,1,IPC_CREAT|00666);
    arc.val=val;
    semctl(sem_id,0,SETVAL,arc);
}

主函数:
int main()
{
 sem_init();
 int mutx;
 int full;
 int empt;
 char *shares;
 int *num;
 int shareid;
 shareid=shmget(5,1280,0777|IPC_CREAT);//用同一个key可以得到同一块共享内存
 shares=(char*)shmat(shareid,0,0);//得到共享内存的指针
 sem_crea(mutx,1);
 sem_crea(full,0);
 sem_crea(empt,1);
 num=(int *)shares;
 pid_t p1;
 pid_t p2;
 p1=fork();//fork在子进程中返回0在父进程中返回子进程的pid_t
 p2=fork();
 if(p1==0)//生产者进程
 {
 int n=20;
 while(n--)
 {
 p(empt);
 *num=n;
 v(full);
 }
 sleep(5);
exec(0);
 }
 else if(p2==0)//两个消费者进程
 {
 while(1)
 {
 p(full);
 p(mutx);
 cout<<"comsumer A :"<<*num<<endl;
  v(mutx);
 v(empt);
 }
 }
 else
 {
 while(1)
 {
 p(full);
 p(mutx);
 cout<<"comsumer B :"<<*num<<endl;
 v(mutx);
 v(empt);
 }
 }
 return 0;
}


  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值