信号量

2015-08-12 18:02:14   最后更新: 2015-08-12 18:13:11   访问数量:573




 

 

线程同步中我们介绍了互斥量:

线程同步

信号量与互斥量类似,也是用来加锁,但是互斥量只能取值 0 或 1,而信号量则可以为任意非负整数

互斥量通常用于多个线程对同一资源的互斥访问,而信号量可以通过取不同的值,让各个线程知道目前阻塞并等待该资源的线程数目,或让多个线程可以对多个资源实现互斥访问

同时,信号量原生的支持了多进程的互斥,而互斥量仅支持线程环境下的互斥,虽然通过将互斥量创建在共享内存中,并将其属性设置为 PTHREAD_PROCESS_SHARED 可以实现在多进程间的共享,但是一旦持有锁的进程意外退出(退出前没有解锁),则所有等待该锁的进程都会陷入死锁,然而,信号量并不存在这个问题

不过信号量的加锁和解锁的效率要比互斥量低一些

 

posix 定义了信号量集,实现了一个或多个信号量的等待:

信号量集

在编译过程中需要与 -lrt 或 -pthread 一起链接

 

下面介绍 unix 下信号量的四种操作,全部定义于 semaphore.h 中:

  1. 初始化匿名信号量 -- sem_init
  2. 创建实名信号量 -- sem_open
  3. 等信号量 -- sem_wait
  4. 尝试等信号量 -- sem_trywait
  5. 发信号 -- sem_post
  6. 清理信号量 -- sem_destory

 

函数原型

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

 

 

返回值

调用成功返回 0,否则返回 -1 并将 errno 置为相应的值

errno 取值
errno意义
EINVALvalue 超过 SEM_VALUE_MAX
ENOSYS系统不支持进程共享的信号量(仅当 pashared 不为零时可能返回)

 

参数

  1. sem -- 指向匿名信号量变量的指针
  2. pshared -- 初始化为进程间共享信号量,为 0 则仅允许进程内的线程共享
  3. value -- 信号量的初始值

 

如果将信号量设置为进程间共享,则该信号量必须在所有的共享进程中都可见,如创建在共享内存中,同样的,如果设置为线程间共享,则所有共享的线程中也必须是都可见的,如创建为全局变量或创建在堆空间中

 

函数原型

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

 

 

返回值

返回指向信号量的指针,出错返回 SEM_FAILED

 

参数

sem_open 参数
参数意义
name信号量外部名称
oflag信号量打开模式
mode权限位
value信号量初始值

 

oflag 可以取 0 或下列取值中的一个或多个的按位或组合

oflag 取值
取值意义
O_CREAT创建信号量,如果指定信号量已存在则直接使用它
O_EXCL通常与 O_CREAT 一起使用,强制创建,如果指定信号量已存在则返回出错

 

如果信号量值不为 0,则将信号量原子的减一,否则阻塞直到信号量不为 0

 

int sem_wait(sem_t *sem);

 

调用成功返回 0,否则返回 -1

 

与 sem_wait 不同,如果信号量为 0,则 sem_trywait 并不会阻塞,而是会返回出错,并将 errno 设置为 EAGAIN

 

int sem_trywait(sem_t *sem);

 

 

sem_trywait 出错返回的 errno 取值
取值意义
EINTR信号处理中断调用
EINVAL信号量无效
EAGAIN无法获取锁

 

原子地将信号量加 1,表示放弃信号量

 

int sem_post(sem_t *sem);

 

调用成功返回 0,否则返回 -1 并将 errno 置为相应的值

 

sem_post 出错返回的 errno 取值
取值意义
EINVAL信号量无效
EOVERFLOW信号量的值超出最大值

 

int sem_destroy(sem_t *sem);

 

调用成功返回 0,否则返回 -1

 






读书笔记      技术帖      龙潭书斋      apue      信号量      sem      sem_t      semaphore     


京ICP备15018585号