Linux下的通信方式之 System_V 信号量
对于每个信号量来说,都用一个结构体:
1 2 3 4 5 struct semid ds {struct ipc_perm sem_perm ;time_t sem_otime:time_t sem_ctime;unsigned long sem_nsems; };
信号量的创建和操作是以集合为单位的,一个集合包含一个或多个信号量。集合中的每个信号量都是一个整数,其值永远大于或等于 0。semop()系统调用允许调用者在一个信号量上加上一个整数、从一个信号量中减去一个整数、或等待一个信号量等于 0。后两个操作可能会导致调用者阻塞。
semget() 1 2 3 4 5 6 7 #include <sys/sem.h> int semget (key_t key, int num_sems, int sem_flags) ; 第一个参数key:一个整型值对应内核中一个信号量对象,可以自己指定,不同信号量的key值不一样。不相关的进程可以通过它访问同一个信号量。程序对所有信号量的访问都是间接的,它先提供一个键,再由系统生成一个响应的信号标识符。 第二个参数num_sems:指定需要的信号量数目。 第三个参数sem_flags:设置一组标志,与open函数的标志非常相似,包括信号量的权限等。IPC_CREAT标志是创建或者使用已有的信号量。 而IPC_CREAT和IPC_EXCL结合使用可以确保创建出的是一个新的、唯一的信号量,如果该信号量已存在,它将返回一个错误。 创建时给出的权限可以是:0600 。 返回值: 成功:正数(非零)值; 失败:-1
作用:第一次使用时创建信号量,以后使用时获取信号量。
注意:如果是创建新的信号量(一般在服务器进程中),则必须指定num_sems。如果是引用现有信号量,则将num_sems指定为0。
semot() 1 2 3 4 5 6 7 8 9 10 #include <sys/sem.h> int semop (int sem_id, struct sembuf *sem_ops, size_t num_sem_ops) ; 第一个参数sem_id:信号量标识符。 第二个参数sem_ops是指向一个结构数组的指针,每个数组元素至少包含以下几个成员:struct sembuf { short sem_num; short sem_op; short sem_flg; };第三个参数num_sem_ops指的是结构数组的元素个数。就上上面这个结构数组。
这里的第四个参数的类型是一个 menu 类型,虽然将 semun union的定义放在标准头文件中是比较明智的做法,但 SUSv3要求程序员显式地定义这个 union。然而,一些 UNIX实现在 <sys/sem.h>
中提供了这个定义。glibc较早以前的版本(2.0以下,包括 2.0)也提供了这个定义。为了与 SUSv3保持一致,glibc最近的版本并没有提供这个定义,并且通过将 <sys/sem.h>
中的_SEM_SEMUN_UNDEFINED宏的值定义为 1来表明这个事实(即使用 glibc编译的应用程序可以通过测试这个宏来确定程序自己是否需要定义 semun union)。
1 2 3 4 5 6 7 8 9 10 #ifndef _SEM_SEMUN_UNDEFINED #define _SEM_SEMUN_UNDEFINED union semun { int val; struct semid_ds *buf ; unsigned short *array ; struct seminfo *__buf ; };#endif
作用:对信号量进行操作,包括P操作(等待)、V操作(发送)、获取信号量值。
semctl() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <sys/shm.h> int semctl (int sem_id, int sem_num, int command,...) ; 第一个参数sem_id:信号量标识符 第二个参数sem_num:信号量编号,当用到成组的信号量,就要用到这个参数。它一般取值为0 ,表示这是第一个信号量。 第三个参数command:要采取的动作 有很多不同的值,有两个常用: SETVAL:用来把信号量初始化成一个已知的值,这个值通过union semun 中的val 成员设置。IPC_RMID :用于删除一个已经无需使用的信号量标识符。第四个参数:可选。是否使用取决于所请求的命令。如果使用该参数,则其类型是semun 。 union semun { int val; struct semid_ds *buf ; unsigned short *array ; }; 一般只使用val这个成员,来为信号量赋初值。当信号量值为0 时,进程会阻塞运行。
作用:初始化或者删除信号量。
信号量的命令操作 在 Linux 中可以使用命令 ipcs -s
来查看系统中所有的信号量。删除信号量可以是 ipcs -s semid
来删除指定的信号量,其中 semid
是信号量标识符。