POSIX信号量的操作

POSIX信号量有两种:有名信号量无名信号量,无名信号量也被称作基于内存的信号量。有名信号量通过IPC名字进行进程间的同步,而无名信号量如果不是放在进程间的共享内存区中,是不能用来进行进程间同步的,只能用来进行线程同步。

POSIX三种操作

创建信号量

创建的过程还要求初始化信号量的值。

根据信号量取值(代表可用资源的数目)的不同,POSIX信号量还可以分为:

  • 二值信号量:信号量的值只有0和1,这和互斥量很类型,若资源被锁住,信号量的值为0,若资源可用,则信号量的值为1;

  • 计数信号量:信号量的值在0到一个大于1的限制值(POSIX指出系统的最大限制值至少要为32767)。该计数表示可用的资源的个数。

等待信号量(wait)/P操作

该操作会检查信号量的值,如果其值小于或等于0,那就阻塞,直到该值变成大于0,然后等待进程将信号量的值减1,进程获得共享资源的访问权限。为原子操作。

挂出一个信号量(post)/V操作

该操作将信号量的值加1,如果有进程阻塞着等待该信号量,那么其中一个进程将被唤醒。

POSIX信号量函数接口

有名信号量的创建和删除

创建

1
2
3
4
5
6
7

#include <semaphore.h>

sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag,
mode_t mode, unsigned int value);
//成功返回信号量指针,失败返回SEM_FAILED
  • 信号量通过name参数即信号量的名字来进行标识
  • oflag参数可以为:0,O_CREAT,O_EXCL,0表示打开一个已存在的信号量,如果为O_CREAT,表示如果信号量不存在就创建一个信号量,如果存在则打开被返回。此时mode和value需要指定。如果为O_CREAT | O_EXCL,表示如果信号量已存在会返回错误。
  • mode参数用于创建信号量时,表示信号量的权限位,和open函数一样包括:S_IRUSR,S_IWUSR,S_IRGRP,S_IWGRP,S_IROTH,S_IWOTH。
  • value表示创建信号量时,信号量的初始值。

删除

1
2
3
4
5
#include <semaphore.h>

int sem_close(sem_t *sem);
int sem_unlink(const char *name);
//成功返回0,失败返回-1
  • sem_close

互斥量和信号量的差别

  • 互斥量必须由给它上锁的线程解锁。而信号量不需要由等待它的线程进行挂出,可以在其他进程进行挂出操作。
  • 互斥量要么被锁住,要么是解开状态,只有这两种状态。而信号量的值可以支持多个进程成功进行wait操作。

  • 信号量的挂出操作总是被记住,因为信号量有一个计数值,挂出操作总会将该计数值加1,然而当向条件变量发送一个信号时,如果没有线程等待在条件变量,那么该信号会丢失。