sem_open、sem_close、sem_unlink
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
#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
int sem_close(sem_t *sem);
int sem_unlink(const char *name);
Link with -pthread.
函数sem_open创建一个新的有名信号量或打开一个已存在的有名信号量。有名信号量总是既可用于线程间的同步,又可用于进程间的同步。
oflag: 0, O_CREAT, O_EXCL
mode: 权限位
value:信号量的初始值,不能超过SEM_VALUE_MAX。
如果指定了O_CREAT,那么第三个和第四个参数是需要的。
使用sem_close关闭有名信号量,但并不将它从系统删除。
使用sem_unlink从系统中删除有名信号量。
一个进程终止时,内核还对其上仍然打开着的所有有名信号量自动执行这样的信号量关闭操作。不论该进程是自愿终止的(通过调用exit或_exit)还是非自愿的(通过向它发送信号),这种自动关闭都会发生。
每个信号量有一个引用计数器记录当前的打开次数,sem_unlink 类似 unlink 函数:当引用计数大于0时,name就能从文件系统中删除,然而其信号量的析构却要等到最后一个sem_close发生时为止。
sem_wait、sem_trywait
#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.
sem_wait函数测试所指定的信号量的值,如果该值大于0,那就将它减1并立即返回。如果该值等于0,调用线程就被投入睡眠中,知道该值变为大于0,这时再将它减 1,函数随后返回。“测试并减 1” 操作必须是原子的。如果被某个信号中断,sem_wait 可能过早返回,错误为EINTR。
sem_trywait , 当信号值已经是0 时,它返回一个EAGAIN错误。
sem_post、sem_getvalue
#include <semaphore.h>
int sem_post(sem_t *sem);
int sem_getvalue(sem_t *sem, int *sval);
// 返回:若成功则为0,出错则为-1
当一个线程使用完某个信号量,它应该调用sem_post。本函数把所指定的信号量的值加 1, 然后唤醒正在等待该信号量值变成正数的任意线程。
sem_getvalue 返回所指定信号量的当前值。如果该信号量当前已上锁,那么返回值或为0,或为某个负数,其绝对值就是等待该信号量解锁的线程数。
sem_init、sem_destroy
此前处理的是有名信号量,这些信号量由一个name参数标识,代指文件系统中的某个文件。POSIX也提供基于内存的信号量。它们由应用程序分配信号量的内存空间,然后由系统初始化它们的值。
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_destroy(sem_t *sem);
如果pshared 为0,那么待初始化的信号量是在同一进程的各个线程间共享的。
否则该信号量是在进程间共享的。
当pshared 非 0 时,该信号量必须存放在某种类型的共享内存区,使用它的所有进程都要能访问该共享内存区。
信号量限制:
SEM_NSEMS_MAX: 一个进程可同时打开着的最大信号量数。
SEM_VALUE_MAX: 一个信号量的最大值。
在<unistd.h>中定义。