linux中的进程通信-信号量和有名管道

来源:互联网 发布:php b2c商城系统二次开 编辑:程序博客网 时间:2024/05/16 02:56

linux中的进程通信-信号量和有名管道

1、为了实现一种通用性对信号量函数进行封装(头文件sys/sem.h)
(1)创建一个或者打开一个信号量集

   void sem_get(int key,int val[],int len)//信号集中信号个数由len确定{    semid=semget((key_t)key,len,0666);    if(semid==-1)    {        semid=semget((key_t)key,len,0666|IPC_CREAT);//确保获取到信号量集        assert(semid!=-1);        union senun v;        int i=0;        for(;i<len;++i)        {           v.val=val[len];           semctl(semid,i,SETVAL,v);        }    }}

(2)p、v操作

void sem_p(int semnum) //资源的使用信号(-1)传参为第几个信号量 (从0开始){    struct sembuf op;    op.sem_num=semnum;    op.sem_op=-1;    op.sem_flg=SEM_UNDO;    semop(semid,&op,1);}void sem_v(int semnum)//资源的释放信号(+1){    struct sembuf op;    op.sem_num=semnum;    op.sem_op=1;    op.sem_flg=SEM_UNDO;    semop(semid,&op,1);}

4、信号的删除

void sem_del(){    semctl(semid,0,IPC_RMID,NULL);}

2、对于两个进程之间的通信 用一个例子来实现:A、B两个进程,A进程负责接收用户输入,B进程负责执行和输出;当用户在A进程中输入”ok”时,B进程输出“我准备好了”,当用户在A进程中输入“走你”时,B进程开始打印100以内所有素数;
(1)方法一:只用信号量控制,用两个信号量sem1和sem2分别控制“ok”和“走你”;

 1>在A进程中:void main(){    int val=2;    sem_get((key_t)1234,&val,2);    printf("进程A开始:\n");    while(1)    {        printf("please input:\n");        char buff[128]={0};        fgets(buff,127,stdin);        buff[strlen(buff)-1]=0;        if(strncmp(buff,"ok",2)==0)        {            sem_v(0);//信号集中的信息从0下标开始 对第一个信号量进行v操作        }        else if(strncmp(buff,"走你",4)==0)        {            sem_v(1);//对第二个信号量进行v操作        }    }}2>在B进程中void main(){    int val=2;    sem_get((key_t)1234,&val,2);    printf("B进程开始:\n");    while(1)    {        sem_p(0);//对第一个信号量进行p操作        printf("我准备好了\n");        sem_p(1);//对第二个信号量进行p操作        printf("我开始计算100以内所有素数\n");        int i=1;        for(;i<100;++i)        {            int j=2;            for(;j<i;++j)            {                if(i%j==0)break;            }            if(i==j || i==1)                printf("%d ",i);        }        printf("\n");    }}

(2)方法二:同时用到了信号量和管道控制:首先设置资源为0,当A进程接收到“ok”时,使用v操作,B进程退出阻塞,输出我准备好了同时进行p操作,当A进程接收到“走你”时,用管道发送“begin”到B进程,B进程开始计算(当然用两个管道阻塞也可以实现)

1>A进程中:void main(){   int val=1;    sem_get((key_t)1234,&val,1);//A、B进程控制同一个信号量    printf("A进程开始:\n");    while(1)    {        printf("please input:\n");        char buff[128]={0};        fgets(buff,128,stdin);        buff[strlen(buff)-1]=0;        if(strncmp(buff,"ok",2)==0)        {            sem_v(0);        }       else if(strncmp(buff,"走你",4)==0)        {            int fd=open("FIFD",O_WRONLY);            assert(fd!=-1);            write(fd,"begin",5);        }    }}2>B进程中void main(){    int val=1;    sem_get((key_t)1234,&val,1);    printf("B进程开始:\n");    while(1)    {        sem_p(0);//资源为0 阻塞等待A进程中的v操作的执行        printf("我准备好了\n");        int fd=open("FIFD",O_RDONLY);//管道阻塞        assert(fd!=-1);        char buff[128]={0};        read(fd,buff,127);        if(strncmp(buff,"begin",5)==0)//判断从管道中读取的数据是否为“begin”        {            printf("我开始计算100以内素数\n");            //省略计算打印过程 参考方法一        }    }}

这里写图片描述

原创粉丝点击