【Linux 进程间通信】信号量

API

int semget(key_t key, int nsems, int semflg);创建或者获取已经存在的信号量
semget()成功返回信号量的ID,失败返回-1
key:两个进程使用相同的key值,就可以使用同一个信号量
nsems:内核维护的是一个信号量集,在新建信号量时,其指定信号量集中信号量的个数
semflg 可选:IPC_CREAT IPC_EXCL
IPC_CREAT|IPC_EXCL,如果内核中不存在这样的信号量,则新建,否则,则报错,semfg使用时要与IPC对象权限进行|运算来设定权限
int semop(int semid, struct sembuf*sops, unsigned nsops);
semop(对信号量进行改变,做Р操作或者V操作
成功返回0,失败返回-1
struct sembuf{
unsigned short sem_num;//指定信号量集中的信号量下标
sem_op;//其值为-1,代表Р操作,其值为1,代表V操作
short sem_flg;//标志位SEM_UNDO,如果程序执行P操作后,程序奔了,不能执行V操作,SEM_UNDO可以记住程序进行了P操作,就算程序奔溃也可以帮助进行V操作,并不会因为程序奔溃而无法进行V操作,一直阻塞其它进程。
};
int semctl(int semid, int semnum, int cmd,...);控制信号量
成功返回0,失败返回-1
cmd选项:SETVAL (赋初值)IPC_RMID(删除)删除时semnum只需要填0就可以了,0只是占参数位置,填0就可以删除所有信号量。
union semun
 {
 int val;
 struct semid_ds *buf;
unsigned short *array;
struct seminfo *_buf;
 }
 此联合体需要用户自己定义

案例:交替打印AB

sem.h

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/sem.h>
#define NUM 2
union semun
{
   int val;
   struct semid_ds * buf;
   unsigned short *array;
   struct seminfo *__buf;
};
void sem_init();
void sem_p(int index);
void sem_v(int index);
void sem_destory();

sem.c

#include"sem.h"
#include<sys/sem.h>
static int semid =-1;
void sem_init()
{
    semid = semget((key_t)1234,NUM,IPC_CREAT|IPC_EXCL|0600);
    if(semid == -1)
    {
      semid = semget((key_t)1234,NUM,0600);
      if(semid == -1)
      {

          printf("semget erro\n");
      }
    }else//
    {
      union semun a;
      int arr [2]={1,0};
      for(int i=0;i<NUM;++i)
      {
       a.val =arr[i];
      if(semctl(semid,i,SETVAL,a) ==-1)
      {
       printf("semctl init erro\n");
      
      }
     }   
    }

}
void sem_p(int index)
{
  if(index <0 || index >=NUM)
  {
   exit(1);
  }
  struct sembuf buf;
  buf.sem_num=index;
  buf.sem_op=-1;
  buf.sem_flg = SEM_UNDO;//yichang zhong duan hou gei xing hao liang v cao zuo
  if(semop(semid,&buf,1) == -1)
  {
  
   printf("semop p erro\n");
  }

}
void sem_v(int index)
{
 
  if(index <0 || index >=NUM)
  {
   exit(1);
  }
  struct sembuf buf;
  buf.sem_num=index;
  buf.sem_op=1;
  buf.sem_flg = SEM_UNDO;//yichang zhong duan hou gei xing hao liang v cao zuo
  if(semop(semid,&buf,1) == -1)
  {
  
   printf("semop v  erro\n");
  }

}
void sem_destory()
{
  if(semctl(semid,0,IPC_RMID) == -1)      
  {
    printf("semctl destory err\n");
  }


}

a.c

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include"sem.h"
int main()
{
  sem_init();  
 for(int i=0;i<5;++i)
 {
  sem_p();
  printf("A");
  fflush(stdout);
  int n = rand()%3;
  sleep(n);
  printf("A");
  fflush(stdout);
  sem_v();
  n = rand()%3;
  sleep(3);
 
 }   
 sleep(10);
 sem_destory();
  exit(0);  
    
}

b.c

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include"sem.h"
int main()
{
  sem_init();  
 for(int i=0;i<5;++i)
 {
  sem_p();
  printf("B");
  fflush(stdout);
  int n = rand()%3;
  sleep(n);
  printf("B");
  fflush(stdout);
  sem_v();
  n = rand()%3;
  sleep(3);
 
 }   
 sleep(10);
  exit(0);  
    
}

在这里插入图片描述
ipcs 查看系统的消息队列,共享内存,信号量
在这里插入图片描述
0x4d2 为16进制,转换为10进制为1234
ipcrm -s 信号量id 删除信号量
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值