POSIX信号量

POSIX信号量进程是3种 IPC(Inter-Process Communication) 机制之一,3种 IPC 机制源于 POSIX.1 的实时扩展。
Single UNIX Specification 将3种机制(消息队列,信号量和共享存储)置于可选部分中。
在 SUSv4 之前,POSIX 信号量接口已经被包含在信号量选项中。
在 SUSv4 中,这些接口被移至了基本规范,而消息队列和共享存储接口依然是可选的。

相比于 XSI 接口,POSIX 信号量接口考虑了更高性能的实现。
POSIX 信号量使用更简单:没有信号量集,在熟悉的文件系统操作后一些接口被模式化了。尽管没有要求一定要在文件系统中实现,但是一些系统的确是这么实现的。
POSIX 信号量在删除时表现更完美。回忆一下,当一个 XSI 信号量被删除时,使用这个信号量标识符的操作会失败,并将 errno 设置成 EIDRM。使用 POSIX 信号量时,操作能继续正常工作直到该信号量的最后一次引用被释放。

POSIX有两种信号量的实现机制:无名信号量和命名信号量。有名信号量和无名信号量的差异在于创建和销毁的形式上,但是其他工作一样。
无名信号量只可以在共享内存的情况下,比如实现进程中各个线程之间的互斥和同步,因此无名信号量也被称作基于内存的信号量;
命名信号量通常用于不共享内存的情况下,比如进程间通信。

在创建信号量时,根据信号量取值的不同,POSIX信号量还可以分为:
二值信号量:信号量的值只有0和1,这和互斥量很类似,若资源被锁住,信号量的值为0,若资源可用,则信号量的值为1;
计数信号量:信号量的值在0到一个大于1的限制值之间,该计数表示可用的资源的个数。

#include <semaphore.h>
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
Link with -pthread.这一句表示 gcc 编译时,要加 -pthread.

sem_wait的作用是,若 sem 小于 0 ,则线程阻塞于信号量 sem ,直到 sem 大于 0 ;否则信号量值减1。
sem_trywait作用与sem_wait相同,只是此函数不阻塞线程,如果 sem 小于 0,直接返回一个错误(错误设置为 EAGAIN )。
sem_timedwait作用也与sem_wait相同,第二个参数表示阻塞时间,如果 sem 小于 0 ,则会阻塞,参数指定阻塞时间长度。abs_timeout 指向一个结构体,这个结构体由从 1970-01-01 00:00:00 +0000 (UTC) 开始的秒数和纳秒数构成。

struct timespec {
    time_t tv_sec;      /* Seconds */
    long   tv_nsec;     /* Nanoseconds [0 .. 999999999] */
}; 
#include <semaphore.h>
int sem_post(sem_t *sem);
Link with -pthread.
返回值:
   若成功,返回 0 ;若出错,返回-1

无名信号量

int sem_init(sem_t *sem, int pshared, unsigned int value);

该函数初始化由sem指向的信号对象,设置它的共享选项,并给它一个初始的整数值。
pshared控制信号量的类型,如果其值为0,就表示信号量是当前进程的局部信号量,否则信号量就可以在多个进程间共享。
value为sem的初始值。
返回值: 该函数调用成功返回0,失败返回-1。

int sem_destroy(sem_t *sem);
int sem_getvalue(sem_t *restrict, int *restrict);

该函数返回当前信号量的值,通过restrict输出参数返回。
如果当前信号量已经上锁(即同步对象不可用),那么返回值为0,或为负数,其绝对值就是等待该信号量解锁的线程数。

有名信号量

sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value);

name是一个标识信号量的字符串。
oflag用来确定是创建信号量还是连接已有的信号量。 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 表示创建信号量时,信号量的初始值。

int sem_close(sem_t *);

单个程序可以用sem_close函数关闭命名信号量,但是这样做并不能将信号量从系统中删除,因为命名信号量在单个程序执行之外是具有持久性的。当进程调用_exit、exit、exec或从main返回时,进程打开的命名信号量同样会被关闭。

sem_unlink函数 功能: sem_unlink函数用于在所有进程关闭了命名信号量之后,将信号量从系统中删除:

int sem_unlink(const char *name);
posted @ 2026-01-20 19:56  老禾的账本  阅读(0)  评论(0)    收藏  举报