博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

posix 信号量 sem_open sem_close sem_unlink

Posted on 2015-05-27 11:10  bw_0927  阅读(2185)  评论(0)    收藏  举报
信号灯(semaphore),也叫信号量。它是不同进程间或一个给定进程内部不同线程间同步的机制。信号灯包括posix有名信号灯、 posix基于内存的信号灯(无名信号灯)和System V信号灯(IPC对象)
总结:
System V的信号量一般用于进程同步, 且是内核持续的, api为
semget
semctl
semop
Posix的有名信号量一般用于进程同步, 有名信号量是内核持续的. 有名信号量的api为
sem_open
sem_close
sem_unlink

Posix的无名信号量一般用于线程同步, 无名信号量是进程持续的, 无名信号量的api为

sem_init

sem_destroy

http://my.oschina.net/u/178323/blog/32588

==========================================

有三种信号量:

1,Posix有名信号量:使用PosixIPC名字标识(通过特定函数,调用一个绝对文件路径名作为参数,返回一个特定标识),可用于进程或线程间通信。

2,Posix基于内存的信号量:存放在共享内存区(进程间共享内存区或者线程间共享内存区),可用于进程或线程间同步。

3,System V信号量:在内核中维护,可用于进程或线程间的同步。

 

Posix信号量不必在内核中维护的,这不同于systemV信号量。

那么信号量、互斥锁和条件变量之间的差异在哪呢?:

1,互斥锁必须总是由给它上锁的线程解锁,信号量的挂出却不用非得由执行它的等待操作线程执行。

2,互斥锁要么被锁住要么被解开(二值状态,类似于二值信号量)。

 

下面我们来讲有名信号量:-------------------------------------------

由于进程间或者线程间同步。

创建或者打开已有的有名信号量:

 

1
2
3
4
5
6
7
8
9
#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);
 
Link with -lrt or -pthread.

 

sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
成功返回信号量指针;失败返回SEM_FAILED,设置errno
name是文件路径名,但不能写成/tmp/a.sem这样的形式,因为在linux下,sem都是在/dev/shm目录下,可写成"/mysem"或"mysem",创建出来的文件都是"/dev/shm/sem.mysem",mode设置为0666,value设置为信号量的初始值.

 

关闭和删除信号量:

 

 

1
2
3
4
5
6
7
#include <semaphore.h>
 
int sem_close(sem_t *sem);
 
int sem_unlink(const char *name);
 
Link with -lrt or -pthread.

 

一个进程关闭了之后,内核会自动的对其上打开的的所有有名信号量自动执行关闭,但这并不代表就删除了此信号量。每个信号量都有一个应用计数器记录当前的打开次数,当记录数大于0时,unlink就将其从文件系统中删除,但是其信号的析构要等到最后一个sem_close发生时为止。

 

 

获取信号量函数:

 

1
2
3
4
5
6
7
8
9
#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 -lrt or -pthread.

 

测试所指定的信号量值,如果此值等于0,那么线程就投入睡眠中,如果大于0,则将此值减一并返回。

 

 

释放信号量函数:

 

1
2
3
4
5
#include <semaphore.h>
 
int sem_post(sem_t *sem);
 
Link with -lrt or -pthread.

 

将制定的信号量加一,并唤醒正在等待该信号量值变为正数的所有线程。

 

这里还有一个函数:

 

1
2
3
4
5
#include <semaphore.h>
 
int sem_getvalue(sem_t *sem, int *sval);
 
Link with -lrt or -pthread.

 

通过sval获得当前信号量值,或者通过返回值要么是0,要么是此时阻塞在这个信号量上的进程或者线程数。

 

下面来讲基于内存的信号量:----------------------------------------------无名信号量,用于进程体内各线程间的互斥和同步,使用如下API(无名信号量,基于内存的信号量)

 

1
2
3
4
5
#include <semaphore.h>
 
int sem_init(sem_t *sem, int pshared, unsigned int value);
 
Link with -lrt or -pthread.

 

它们由应用程序分配一个信号量的内存空间,然后通过这个函数初始化它。

 

这里,涉及到是进程间共享的还是线程间共享的要分两种看待:

1,进程间共享的:那么应用程序就应该在进程间共享内存区分配一个信号量的内存空间,同时shard的值为nonezero。

2,线程间共享的,那么应用程序就应该在线程间共享内存区分配一个信号量的内存空间,同时shared的值为zero。

释放基于内存的信号量:

 

1
2
3
4
5
#include <semaphore.h>
 
int sem_destroy(sem_t *sem);
 
Link with -lrt or -pthread.