欢迎访问我的网站,希望内容对您有用,感兴趣的可以加入我们的社群。

进程间通信之信号量

C/C++ 迷途小书童 6年前 (2019-03-10) 2394次浏览 0个评论

说到底,信号量就是用来控制多个进程对共享资源使用的一个计数器

相关数据结构

1、sem

信号量对象是多个信号量的集合,而这个集合在linux中是以数组的形式实现的,数组的每个成员都是一个单独的信号量,即sem结构

  1. struct
  2. {
  3. short sempid; /*最近一次操作信号量的进程的id*/
  4. unsigned short semval; /*信号量的计数值*/
  5. unsigned short semncnt; /*等待使用资源的进程数目*/
  6. unsigned short semzcnt; /*等待资源完全空闲的进程数目*/
  7. }

2、semun

  1. union semun
  2. {
  3. int val; /* value for SETVAL */
  4. struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
  5. unsigned short *array; /* array for GETALL & SETALL */
  6. struct seminfo *__buf; /* buffer for IPC_INFO */
  7. void *__pad;
  8. };

3、sembuf

被用来定义对信号量对象的基本操作

  1. struct sembuf
  2. {
  3. unsigned short sem_num; /* 接受操作的信号量在信号量数组中的序号,即数组下标 */
  4. short sem_op; /* 定义了进行的操作,取值正、0和负值 */
  5. short sem_flg; /* 控制操作行为的标志 */
  6. };
  • 如果sem_op值为负,就从指定的信号量中减去相应的值,对应着获取信号量所监控的资源的操作。若sem_flg中没有指定IPC_NOWAIT标志,如果现有的信号量数值小于sem_op的绝对值(表示现有资源少于所需资源),调用semop()的进程就会阻塞直到信号量的数值大于sem_op的绝对值(表示有足够的资源)。

  • 如果sem_op值为正,就在指定的信号量中加上相应的值,这对应着释放信号量所监控的资源的操作。

  • 如果sem_op值为零,调用semop()的进程会被阻塞直到对应的信号量值为0。这操作就是等待信号量所监控的资源被全部使用。利用这个操作可以动态监控资源的使用并调整资源的分配,避免不必要的等待。

4、semid_ds

  1. struct semid_ds
  2. {
  3. struct ipc_perm sem_perm; /* permissions .. see ipc.h */
  4. __kernel_time_t sem_otime; /* 最近一次semop操作的时间 */
  5. __kernel_time_t sem_ctime; /* 信号量对象最近一次改动发生的时间 */
  6. struct sem *sem_base; /* 信号里数组的起始地址 */
  7. struct sem_queue *sem_pending; /* 指向还未进行的操作 */
  8. struct sem_queue **sem_pending_last; /* 指向最后一个还未进行的操作 */
  9. struct sem_undo *undo; /* undo requests on this array */
  10. unsigned short sem_nsems; /* 信号量数组成员数目 */
  11. };

msqid_ds类似,semid_ds用来储存每个信号量对象的有关信息。

相关函数

1、semget()

  1. #include <sys/types.h>
  2. #include <sys/ipc.h>
  3. #include <sys/sem.h>
  4. int semget(key_t key, int nsems, int semflg);

semget建立新的信号量对象或者获取已有对象的标识符。参数semflg与消息队列中的msgflg参数取值一样。参数nsems是信息量对象中信号量的数目,也就是信号量数组成员的个数。/usr/include/linux/sem.h中定义了它的上限

  1. #define SEMMSL 250

2、semop()

  1. #include <sys/types.h>
  2. #include <sys/ipc.h>
  3. #include <sys/sem.h>
  4. int semop(int semid, struct sembuf *sops, unsigned nsops);

semop()用来改变信号量对象中各个信号量的状态。参数sopssembuf类型的数组,定义了semop()函数所要进行的操作序列;参数nsopssops数组的长度也就是semop()进行的操作个数。

3、semctl()

  1. #include <sys/types.h>
  2. #include <sys/ipc.h>
  3. #include <sys/sem.h>
  4. int semctl(int semid, int semnum, int cmd, ...);

semctl()直接来控制信号量对象。semid为信号量对象标识符,semnum信号量在集合中的序号。根据cmd的取值,可带第4个参数,union semun argcmd可取如下值

  • IPC_STAT: 取得semidsemid_ds信息,并存放在argbuf
  • IPC_SET: 用arg中的buf设定信号量对象的semid_ds结构
  • IPC_RMID: 删除信号量对象
  • GETALL: 取得信号量对象所有信号量的值,并存放在argarray中返回
  • GETNCNT: 返回正在等待使用某个信号量所控制的资源的进程数目
  • GETPID: 返回最近一个对某个信号量调用semop()的进程的pid
  • GETVAL: 返回集合中最后一个信号量的semval
  • GETZCNT: 返回正在等待某个信号量所控制资源被全部使用的进程数目
  • SETALL:用argarray来设定对象内处个信号量的值
  • SETVAL: 用argval的值来设定对象中某个信号量的值
喜欢 (0)

您必须 登录 才能发表评论!