一、信号量的定义
信号量是一种用于提供不同进程间或一个给定进程下的不同线程间进行同步的手段。
信号量类别 | 使用方式 |
---|---|
Posix有名信号量 | 使用Posix IPC名字标识 |
Posix基于内存的信号量 | 存放在共享内存区 |
System V信号量 | 在内核中维护 |
二、Posix信号量的选择
- 单个进程的各个线程共享,可以使用基于内存的信号量;
- 彼此无亲缘关系的不同进程需要使用信号量时,通常使用有名信号量。
基于内存的信号量的持续性
- 如果某个基于内存的信号量是由单个进程的各个线程共享的(sem_init的shared参数为0),那么该信号量具有随进程的持续性,当该进程终止时它也消失。
- 如果某个基于内存的信号量是在不同进程间共享的(sem_init的shared参数为1),那么该信号量必须存放在共享内存区中,因而只要该共享内存区依然存在,该信号量也就继续存在。
三、信号量分类
Posix | 二值信号量 | 其值为0或1的信号量 |
计数信号量 | 其值在0或某个限制值 | |
System V | 计数信号量集 | 一个或多个信号量(构成一个集合),其中每个都是计数信号量 |
注意: 当谈论Posix信号量时,所指的是单个计数信号量;当谈论System V信号量时,所指的是计数信号量集。
四、Posix信号量
- sem_open()函数
用于创建一个新的有名信号量或打开一个已经存在的有名信号量。sem_open不需要类似于shared的参数或类似于PTHREAD_PROCESS_SHARED的属性,因为有名信号量总是可以在不同进程间共享。
参数name:有名信号量的名字;#include <fcntl.h> #include <sys/stat.h> #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);
参数oflag:0、O_CREAT、O_CREAT|O_EXCL;
参数mode:指定权限位(设置O_CREAT时才需要);
参数value:指定信号量的初值(设置O_CREAT时才需要)。
返回值:若成功则返回指向信号量的指针,出错则返回SEM_FAILED。 - sem_close()函数
关闭由sem_open()打开的有名信号量。
参数sem:要关闭的有名信号量的指针;#include <semaphore.h> int sem_close(sem_t *sem);
返回值:若成功则返回0,若出错则返回-1。注意: 关闭一个信号量并没有将它从系统中删除,即使当前没有进程打开着这个信号量,它的值也仍然会保持。
- sem_unlink()函数
从系统中删除有名信号量。
参数name:有名信号量的名字;#include <semaphore.h> int sem_unlink(const char *name);
返回值:若成功则返回0,若出错则返回-1。注意: 当引用计数大于0时,name就能从文件系统中删除,然而其信号量的析构(不同于将它的名字从文件系统删除)却要等最后一个sem_close发生为止。
- sem_wait()函数
等待信号量,如果该值大于0,那么就将它减1并立即返回。如果该值等于0,调用线程就将进入睡眠,直到该值变为大于0,此时再将它减1,函数随后返回。
参数sem:等待的信号量的指针;#include <semaphore.h> int sem_wait(sem_t *sem);
返回值:若成功则返回0,若出错则返回-1。 - sem_trywait()函数
当所指定的信号量为0时,调用线程将不会进入睡眠等待,而是直接返回一个EAGAIN的错误。如果信号量的值大于0,则把信号量减1,然后返回。
参数sem:等待的信号量的指针;#include <semaphore.h> int sem_trywait(sem_t *sem);
返回值:若成功则返回0,若失败则返回-1 - sem_post()函数
释放信号量,把所指定的信号量加1,然后唤醒正在等待该信号量变为正数的所有线程。
参数sem:待释放的信号量的指针;#include <semaphore.h> int sem_post(sem_t *sem);
返回值:若成功则返回0,若出错则返回-1。 - sem_getvalue()函数
获取指定信号量的当前值。
参数sem:指定的信号量的指针;#include <semaphore.h> int sem_getvalue(sem_t *sem, int *sval);
参数sval:用于保存所指定信号量的当前值。若有一个或者多个线程正在调用sem_wait()阻塞在该信号量上,该函数返回阻塞在该信号量上进程或线程的个数。
返回值:若成功则返回0,若出错则返回-1。 - sem_init()函数
基于内存的信号量初始化。
参数sem:要初始化的内存信号量。#include <semaphore.h> int sem_init(sem_t *sem, int pshared, unsigned int value);
参数shared:如果为0,那么待初始化的信号量是在同一进程的各个线程间共享的,否则该信号量是在进程间共享的。
参数value:信号量的初始值。
返回值:若成功则返回0,若出错则返回-1。 - sem_destroy()函数
销毁基于内存的信号量。
参数sem:待销毁的信号量的指针;#include <semaphore.h> int sem_destroy(sem_t *sem);
返回值:若成功则返回0,若出错则返回-1。