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

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");
            //省略计算打印过程 参考方法一
        }
    }
}

这里写图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值