Linux中POSIX信号量代码解析(P/V操作) |
您所在的位置:网站首页 › 信号量的pv操作方法是 › Linux中POSIX信号量代码解析(P/V操作) |
文章目录
POSIX信号量
1. 基本概念2. POSIX匿名信号量2. 定义2.2 初始化2.3 P/V 操作
3. POSIX具名信号量3.1 创建和打开3.2 P/V 操作3.3 关闭、删除和其他注意事项
POSIX信号量
1. 基本概念
POSIX信号量与IPC信号量组中的信号量元素的逻辑完全一样,但POSIX信号量操作更加简便,接口更加易用。在多进程多线程中运用广泛。 POSIX信号量分成两种: POSIX匿名信号量 通常用在线程间 只存在于内存,在文件系统中不可见 POSIX具名信号量 通常用在进程间 存在于文件系统/dev/shm中,可被不同进程操作 2. POSIX匿名信号量 2. 定义 #include sem_t s; 2.2 初始化 #include int sem_init(sem_t *sem, int pshared, unsigned int value);接口说明: sem:待初始化信号量指针 pshared:指定信号量的作用范围 0:作用于进程内的线程间 非0:作用于进程间 value:信号量的初始值 示例 sem_t s; int main() { // 初始化POSIX匿名信号量: // 将其设定为在本进程内的个线程间使用 // 并将其初始值设定为1 sem_init(&s, 0, 1); } 2.3 P/V 操作POSIX信号量(不管是匿名的还是具名的)的 P/V 操作相对于systemV的信号量组而言,接口非常简单: #include int sem_wait(sem_t *sem); // P操作 int sem_post(sem_t *sem); // V操作 接口说明: P操作即申请资源,因此 sem_wait()在资源不足时会阻塞,V操作是释放资源,且V操作永远不会阻塞 示例 #include sem_t s; char buf[100]; void *routine(void *arg) { while(1) { // 申请信号量-1,输出字符串的长度 p操作 sem_wait(&s); printf("%d\n", strlen(buf)); } } int main() { // 初始化,信号量初始值为0 sem_init(&s, 0, 0); pthread_t t; pthread_create(&t, NULL, routine, NULL); while(1) { fgets(buf, 100, stdin); // 输入字符串后,释放信号量+1 v操作 sem_post(&s); } } 3. POSIX具名信号量POSIX 具名信号量主要用在多进程间同步互斥,其 P/V 操作与匿名版本无异,其最大的特点是存在于文件系统 /dev/shm 中,可以被系统中任意有权限的进程打开。 3.1 创建和打开POSIX 具名信号量使用如下接口创建: #include /* For O_* constants */ #include /* For mode constants */ #include sem_t *sem_open(const char *name, int oflag); sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);说明 与文件IO函数 open() 类似,sem_open() 也提供了两个版本,初建时需要指定文件权限 mode 和初始值 value,后续再打开使用时则无需指定。 示例 // 在进程 a.c 中创建具名信号量 int main() { // 创建有名信号量,参数1代表初始值为1 sem_t *s = sem_open("mysem", O_CREAT, 0666, 1); }// 在进程 b.c 中打开具名信号量 int main() { // 打开具名信号量 sem_t *s = sem_open("mysem", O_RDWR); }编译程序 a.c(注意要加线程库 -lpthread)并运行该程序,便会在系统 /dev/shm/ 产生对应的文件: gec@ubuntu:~$ gcc a.c -o a -lpthread gec@ubuntu:~$ ./a gec@ubuntu:~$ ls -l /dev/shm/ 总用量 4 -rw-rw-r-- 1 gec gec 32 Nov 26 18:27 sem.mysem gec@ubuntu:~$ 3.2 P/V 操作与匿名信号量完全一致: #include int sem_wait(sem_t *sem); // P操作 int sem_post(sem_t *sem); // V操作示例 // a.c int main() { sem_t *s = sem_open("mysem", O_CREAT, 0666, 0); printf("A\n"); sem_post(s); // V操作 } // b.c int main() { sem_t *s = sem_open("mysem", O_RDWR); // 等待A执行完毕,才执行B sem_wait(s); // P操作 printf("B\n"); }信号量的V操作就像一个远程开关,控制另一个进程的进度:在进程A尚未执行 sem_post(s) 之前,进程B会一直在 sem_wait(s) 静静等待,这就是多进程进度控制。 注意,上述程序 a.c 和程序 b.c 是两个独立的程序,彼此之间没有任何共享的变量和数据,他们通过基于文件系统的具名信号量达成协同。 3.3 关闭、删除和其他注意事项POSIX 具名信号量跟文件操作非常类似,打开之后会在内核需要对其维护,因此在不再需要的时候应该予以关闭: sem_close(s);另外,即使所有进程都关闭了信号量并且退出,具名信号量对应的文件是不会消失的,并且会保留所有 P/V 操作后的值,如果不再需要这个文件本身,则除了可以直接在文件系统中删除外,也可以使用如下接口删除: sem_unlink("mysem");上文提到,具名信号量会将所有的 P/V 操作后的值,因此向上述程序 a.c 如果连续执行三遍,那么信号量的值将会被 +3 ,因此程序 b.c 可以连续进行三次 P 操作。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |