目录
- POSIX 信号量有两种类型:匿名信号量和命名信号量,其本质是计数型信号量,计数型信号量参考:https://blog.csdn.net/Liangren_/article/details/108593071。
- 匿名信号量只存在于内存中,这就要求使用信号量的线程必须可以访问内存,因此匿名信号量可以应用于同一进程中线程间的通信,不同的进程间需要映射这段内存到自己的地址空间。
- 命名信号量可以通过名字访问,因此可以应用于进程间的通信。
一个
POSIX
命名信号量必须要调用
sem_open
函数创建或打开之后才能使用;
当一个
POSIX
命名信号量使用完毕后,应该调用
sem_close
函数将其关闭;
当一个
POSIX命名信号量不再有任何用途时,应该调用 sem_unlink
函数删除它,
SylixOS
会回收该信号量占用的内核资源。
1、Open
#include <semaphore.h>
sem_t *sem_open(const char *name, int flag, ...);
函数 sem_open 原型分析:
- 此函数成功时返回一个 sem_t 类型的指针,失败时返回 NULL 并设置错误号;
- 参数 name 是 POSIX 命名信号量的名字;
- 参数 flag 是 POSIX 命名信号量的打开选项(O_CREAT,O_EXCL...);
- 参数…是可变参数,通常可指定打开的模式(mode 和 value)。
如果需要创建一个 POSIX 命名信号量,打开选项应该加上 O_CREAT,并且可变参数应指定 mode 和 value
的值。
如果需要打开一个已经存在的
POSIX
命名信号量,打开选项不能够包含
O_CREAT
选项标志。
2、Wait
线程如果需要等待一个 POSIX 信号量,可以调用 sem_wait 函数,中断服务程序不能调用任何的 POSIX 信号量 API。释放一个信号量使用 sem_post 函数。
#include <semaphore.h>
int sem_wait(sem_t *psem);
int sem_trywait(sem_t *psem);
int sem_timedwait(sem_t *psem, const struct timespec *abs_timeout);
int sem_reltimedwait_np(sem_t *psem, const struct timespec *rel_timeout);
以上几个函数原型分析:
- 函数成功返回 0,失败返回-1 并设置错误号;
- 参数 psem 是 POSIX 信号量的指针;
- 参数 timeout 是等待的绝对超时时间;
- 参数 rel_timeout 是等待的相对超时时间。
sem_trywait 是 sem_wait 的“尝试等待”版本,在 POSIX 信号量的值为 0 时, sem_wait将阻塞直至被唤醒,而 sem_trywait 将立即返回。
sem_timedwait 是 sem_wait 的带等待超时时间的版本, timeout 为等待的绝对超时时间,用时在当前时间的基础上再加上一个相对超时时间就能得到绝对超时时间 timeout,如:
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 1;
sem_timedwait(&sem, &ts);
sem_reltimedwait_np 是 sem_timedwait 的非 POSIX 标准版本,参数 rel_timeout 为等待的相对超时时间,如:
struct timespec ts;
ts.tv_sec = 1;
ts.tv_nsec = 0;
sem_reltimedwait_np(&sem, &ts);
可以看出在使用上,sem_reltimedwait_np 比 sem_timedwait 更方便。
3、Post
#include <semaphore.h>
int sem_post(sem_t *psem);
函数 sem_post 原型分析:
- 此函数成功返回 0,失败返回-1 并设置错误号;
- 参数 psem 是 POSIX 信号量的指针。
4、Close
#include <semaphore.h>
int sem_close(sem_t *psem);
函数 sem_close 原型分析:
- 此函数成功返回 0,失败返回-1 并设置错误号;
- 参数 psem 是 POSIX 命名信号量的指针;
调用
sem_close
函数将减少一次命名信号量的使用计数,但不会删除一个命名信号量,需要注意的是,如果调用 sem_close
函数企图关闭一个匿名信号量,将返回
-1
并设置
errno为 EINVAL
。
5、Delete
#include <semaphore.h>
int sem_unlink(const char *name);
函数 sem_unlink 原型分析:
- 此函数成功返回 0,失败返回-1 并设置错误号;
- 参数 name 是 POSIX 命名信号量的名字。
sem_unlink
函数将删除一个不再使用的命名信号量,并释放系统资源。
sem_unlink
函数会首先判断信号量的使用计数,如果使用计数到达了 0
,则删除信号量,如果没有到达
0
,则出错返回,并设置 errno
为
EBUSY
。