http://blog.csdn.net/sicofield/article/details/10897091
1.引言
信号量是包含一个非负整型变量,并且带有两个原子操作wait 和signal。wait 还可以被称为down、P 或lock,signal 还可以被称为up、V、unlock 或post。在Uinx的API中用的是wait和post。
如果信号量的非负整形变量S大于零,wait就将其减1,如果S 等于0,wait 就将调用线程阻塞。对于signal 操作,如果有线程在信号量上阻塞(此时S 等于0),signal就会解除对某个等待线程的阻塞,使其从wait 中返回,如果没有线程阻塞在信号量上,signal 就将S加1。
由此可见,S 可以被理解为一种资源的数量,信号量即是通过控制这种资源的分配来实现互斥和同步的。如果把S 设为1,信号量即可实现互斥量的功能。如果S 的值大于1,那么信号量即可使多个线程并发运行。另外,信号量不仅允许使用者申请和释放资源,而且还允许使用者创造资源,这就赋予了信号量实现同步的功能。可见,信号量的功能要比互斥量丰富许多。
POSIX信号量是一个sem_t 类型的变量,但POSIX 有两种信号量的实现机制:无名信号量和命名信号量。无名信号量可以用在共享内存的情况下,比如实现进程中各个线程之间的互斥和同步。命名信号量通常用于不共享内存的情况下,比如不共享内存的进程之间。
Posix信号量调用函数
2.POSIX 无名信号量
在使用信号量之前,必须对其进行初始化。sem_init 函数初始化指定的信号量:
#include <semaphore.h> int sem_init(sem_t *sem, int pshared,unsigned value); //成功返回0,出错返回错误号
参数value 为信号量的初始值。参数pshared用于说明信号量的共享范围,如果pshared 为0,那么该信号量只能由初始化这个信号量的进程中的线程使用,如果pshared 非零,任何可以访问到这个信号量的进程都可以使用这个信号量。
函数sem_destroy 销毁一个指定的信号量,它的形式为:
#include <semaphore.h> int sem_destroy(sem_t *sem); //成功返回0,出错返回错误号
信号量的操作函数为sem_post、sem_wait、sem_trywait:
#include <semaphore.h> int sem_post(sem_t *sem); int sem_wait(sem_t *sem); int sem_trywait(sem_t *sem); //成功返回0,出错返回错误号 //sem_trywait函数试图获取信号量,但是如果获取不了,并不阻塞线程,与//pthread_mutex_trylock类似
这些函数同样可以使用与命名信号量!
3.POSIX 命名信号量
之所以称为命名信号量,是因为它有一个名字、一个用户ID、一个组ID和权限,这些是提供给不共享内存的那些进程使用命名信号量的接口。命名信号量的名字是一个遵守路径名构造规则的字符串。
sem_open函数用于创建或打开一个命名信号量:
#include <semaphore.h> sem_t *sem_open(const char *name, intoflag);
参数 name 是一个标识信号量的字符串。参数oflag 用来确定是创建信号量还是连接已有信号量。如果设置了oflag 的O_CREAT 比特位,则会创建一个新的信号量。
sem_close函数用于关闭命名信号量:
#include <semaphore.h> int sem_close(sem_t *sem); //成功返回0,出错返回错误编号
单个程序可以用sem_close函数关闭命名信号量,但是这样做并不能将信号量从系统中删除,因为命名信号量在单个程序的执行之外是具有持久性的。当进程调用_exit、exit、exec 或从main 返回时,进程打开的命名信号量同样会被关闭。
sem_unlink函数用于在所有进程关闭了命名信号量之后,将信号量从系统中删除。它的形式为:
#include <semaphore.h> int sem_unlink(const char *name); //成功返回0,出错返回-1