UNP(卷2:进程间通信)—— 第11章:System V 信号量

先前介绍的POSIX信号量概念:

  • 二值信号量:0,1
  • 计数信号量:0和某个限制值之间的信号量。

System V 中信号量:

计数信号量集:一个或多个信号量,其中每个都是计数信号量。

对于系统的每个信号量集,内核维护一个信息结构:<sys/sem.h>中定义

/* Data structure describing a set of semaphores.  */
struct semid_ds
{
  struct ipc_perm sem_perm;            /* operation permission struct */
  __time_t sem_otime;                  /* last semop() time */
  __syscall_ulong_t __glibc_reserved1;
  __time_t sem_ctime;                  /* last time changed by semctl() */
  __syscall_ulong_t __glibc_reserved2;
  __syscall_ulong_t sem_nsems;         /* number of semaphores in set */
  __syscall_ulong_t __glibc_reserved3;
  __syscall_ulong_t __glibc_reserved4;
};


semget、semop、semctl

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

int semget(key_t key, int nsems, int semflg);
                                                      // 返回:若成功返回非负标识符,出错为-1

int semop(int semid, struct sembuf *sops, size_t nsops);
                                                      // 返回:若成功返回0,出错为-1

int semtimedop(int semid, struct sembuf *sops, size_t nsops, const struct timespec *timeout);

int semctl(int semid, int semnum, int cmd, ...);
                                                      // 返回:成功返回非负值,出错-1

semget 函数:创建一个信号量集,或者访问一个已存在的信号量集。

  • 返回值:一个称为信号量标识符的整数。
  • nsems参数:指定集合中的信号量数。若不创建,只访问一个信号量集,可以设置为0。一旦创建,就不能改变其中的信号量数。
  • semflg:SEM_R 和SEM_A的组合。R表示read。A表示alter。还可以与IPC_CREAT、IPC_EXCL按位与。

当创建一个信号量集时,semid_ds结构中的以下成员被初始化:

  • sem_perm 结构中的uid 和 cuid 成员被置为调用进程的有效用户ID,gid 和 cgid 成员被置为调用进程的有效组ID。
  • semflg参数中的读写权限位存入sem_perm.mode。
  • sem_otime被置为0,sem_ctime则被置为当前时间。
  • sem_nsems被置为nsems参数的值。
  • 与该集合中每个信号量关联的各个sem结构并不初始化。这些结构是在以SET_VAL或SETALL命令调用semctl时初始化的。

semop 函数:打开后,对其中一个或者多个信号量的操作。

其中sembuf结构:

/* Structure used for argument to `semop' to describe operations.  */
struct sembuf
{
   unsigned short int sem_num;   /* semaphore number (0,1,...,nsems-1) */
   short int sem_op;             /* semaphore operation */
   short int sem_flg;            /* operation flag ( 0, IPC_NOWAIT, SEM_UNDO ) */
};

/* Flags for `semop'.  */
#define SEM_UNDO    0x1000      /* undo the operation on exit */

sem_op:正数,0,负数


semctl 函数:对一个信号量执行各种控制操作。

semnum参数:信号量成员。仅仅用于GETVAL、SETVAL、GETNCNT、GETZCNT、GETPID命令。

第四个参数是可选的,取决于第三个参数cmd。

注意:这个联合需要应用自己定义,它是按值传递的,不是按引用传递的。

/* Commands for `semctl'.  */
#define GETPID      11      /* get sempid */
#define GETVAL      12      /* get semval */
#define GETALL      13      /* get all semval's */
#define GETNCNT      14      /* get semncnt */
#define GETZCNT      15      /* get semzcnt */
#define SETVAL      16      /* set semval */
#define SETALL      17      /* set all semval's */

/* Control commands for `msgctl', `semctl', and `shmctl'.  */
#define IPC_RMID    0       /* Remove identifier.  */
#define IPC_SET     1       /* Set `ipc_perm' options.  */
#define IPC_STAT    2       /* Get `ipc_perm' options.  */

union semun {
   int              val;    /* Value for SETVAL */
   struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
   unsigned short  *array;  /* Array for GETALL, SETALL */
   struct seminfo  *__buf;  /* Buffer for IPC_INFO (Linux-specific) */
};

struct  seminfo
{
  int semmap;
  int semmni;
  int semmns;
  int semmnu;
  int semmsl;
  int semopm;
  int semume;
  int semusz;
  int semvmx;
  int semaem;
};
GETVAL ---把semval的当前值作为函数返回值返回。既然信号量绝不会是负数(semval被声明成一个整数unsigned short),那么成功的返回值总是非负数。

SETVAL ---把semval值设置成为arg.val。如果操作成功,那么相应信号量在所有进程中的信号量调整值(semadj)将被置为0。

GETPID ---把sempid的当前值作为函数返回值返回。

GETNCNT---把semncnt的当前值作为函数返回值返回。

GETZCNT---把semzcnt的当前值作为函数返回值返回。

GETALL----返回所指定信号量集内每个成员的semval值。这些值通过arg.array指针返回,函数本身的返回值则为0。注意,调用者必须分配一个unsigned short整数数组,该数组要足够容纳所指定信号量集内所有成员的semval值,然后把arg.array设置成指向这个数组。

SETALL----设置所指定信号量集中每个成员的semval值。这些值是通过arg.array指针指定的。

IPC_RMID--把由semid指定的信号量集从系统中删除掉。

IPC_SET---设置所指定信号量集的semid_ds结构中的以下三个成员:sem_perm.uid、sem_perm.gid和sem_perm.mode,这些值来自由arg.buf参数指向的结构中的相应成员。semid_ds结构中的sem_ctime成员也被设置成当前时间。

IPC_STAT--(通过arg.buf参数)返回所指定信号量集当前的semid_ds结构。注意,调用者必须首先分配一个semid_ds结构,并把arg.buf设置成指向这个结构。


信号量限制:




















发布了98 篇原创文章 · 获赞 74 · 访问量 15万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章