linux 进程通信之信号量

信号量 Linux函数semget();semctl();semop();

信号量三个函数

头文件#include<sys/sem.h>

int semget(key_t  _key ,int  _nsems,int _semflg);
int semctl(int _semid  ,int _semnum,int _cmd  ……);
int semop(int   semid ,struct    sembuf   *_sops ,size_t  _nsops);

semget

int semget(key_t  _key ,int  _nsems,int _semflg);
  • 功能:创建一个新的信号量或获取一个已经存在的信号量的键值。
  • 返回值:成功返回信号量的标识码ID。失败返回-1;

参数

  • _key:信号集的键值,注意是信号集,一个信号集会包含多个信号量,这个键值用来在多个进程中表示到同一个信号集,跟进程PID类似,如果系统已存在一个信号集的键值,那么申请到的就是同一个信号集
  • _nsems:这个信号集里面有多个信号量
  • _semflg:
    • IPC_CREAT如果信号量不存在,则创建一个信号量,否则获取。
    • IPC_EXCL只有信号量不存在的时候,新的信号量才建立,否则就产生错误。

示例

int semid=semget(8888,2,IPC_CREAT|0666);
//创建了一个键值为8888,权限为666的信号集,同时这个信号集包含了两个信号量

semctl

int semctl(int _semid  ,int _semnum,int _cmd  ……);
  • 功能:控制信号量的信息。
  • 返回值:成功返回0,失败返回-1;

参数

  • _semid:信号集的标志码(ID),也就是semget()函数的返回值;
  • _semnum:信号在信号集中的序号。从0开始排序
  • _cmd:
    • IPC_STAT读取一个信号量集的数据结构semid_ds,并将其存储在semun中的buf参数中。
    • IPC_SET设置信号量集的数据结构semid_ds中的元素ipc_perm,其值取自semun中的buf参数。
    • IPC_RMID将信号量集从内存中删除。
    • GETALL用于读取信号量集中的所有信号量的值。
    • GETNCNT返回正在等待资源的进程数目。
    • GETPID返回最后一个执行semop操作的进程的PID。
    • GETVAL返回信号量集中的一个单个的信号量的值。
    • GETZCNT返回这在等待完全空闲的资源的进程数目。
    • SETALL设置信号量集中的所有的信号量的值。
    • SETVAL设置信号量集中的一个单独的信号量的值。
  • Semunion:第4个参数是可选的,一般是union semun的实例
    这个联合体是需要自己定义的
      union semun {
          int   val;
          struct   semid_ds  *buf;
          unsigned short   *arrary;
      };
    
    _cmd为设置时,比如_cmd=SETALL,那么Semunion就是设置信号量的值
    _cmd为获取时,比如_cmd=GETALL,那么Semunion就是获取信号量的值

示例代码

如果要设置全部信号量的值

union semun {
        int   val;
        struct   semid_ds  *buf;
        unsigned short   *arrary;
    };

union semun  sem_args;
unsigned short array[3]={1, 2, 4}; //信号集里面信号量的值分别是: 1, 2, 4
sem_args.array = array;
ret = semctl(semid, 0, SETALL, sem_args);//当_cmd=SETALL时,第二个参数是什么都无所谓
if (-1 == ret){
    perror("semctl");
    exit(EXIT_FAILURE);
}

如果要获取全部信号量的值

union semun  sem_args;
unsigned short array[3];
sem_args.array = array;
ret = semctl(semid, 0, GETALL, sem_args);//当_cmd=GETALL时,第二个参数是什么都无所谓
if (-1 == ret){
    perror("semctl");
    exit(EXIT_FAILURE);
}
//array[]数值分别存储着各个信号量的值,当然是按顺序排好的

semop

int semop(int semid ,struct sembuf *_sops ,size_t _nsops);
  • 功能:用户改变信号量的值。也就是使用资源还是释放资源使用权。
  • 返回值:成功返回0,失败返回-1;

参数

  • semid:信号集的标志码(ID),也就是semget()函数的返回值;
  • _sops是一个指向结构体数组的指针。
struct sembuf{
    unsigned short sem_num;//第几个信号量,第一个信号量为0;
    short sem_op;//对该信号量的操作。
    short semflg;
};
  1. sem_op:
    1. sem_op=1:释放信号量,信号量的值+1
    2. sem_op=-1:等待一个信号量,信号量的值-1
      当信号量的值为0时,获取失败信号量失败
  2. _semflg:
    1. IPC_NOWAIT:等不到信号量不会阻塞(非阻塞式)
    2. IPC_UNDO:等不到信号量就阻塞(阻塞式等待)
  • nsops:操作结构的数量,恒大于或等于1

示例

struct sembuf sem_b;

sem_b.sem_num = 0;  //第0个信号量
sem_b.sem_op = 1;   //释放一个信号量,信号量的值+1
sem_b.sem_flg = SEM_UNDO; //不阻塞      当信号量的值为0时,获取信号量失败,阻塞
if(semop(semid, &sem_b, 1) == -1){
    fprintf(stderr, "error\n");
    return -1;
}
posted @   重力弹力支持力  阅读(75)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示