在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量。无名信号量一般用于线程间同步或互斥,而有名信号量一般用于进程间同步或互斥。它们的区别和管道及命名管道的区别类似,无名信号量则直接保存在内存中,而有名信号量要求创建一个文件。前面我们学习了无名信号量的使用(详情请看《无名信号量》),这里我们学习有名信号量的使用。

1)创建一个有名信号量

所需头文件:

#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);

功能:

创建一个有名信号量。

参数:

name:信号量文件名。注意,不能指定路径名。因为有名信号量,默认放在/dev/shm 里,如下图:

flags:sem_open() 函数的行为标志。

mode:文件权限(可读、可写、可执行)的设置。

value:信号量初始值。

返回值:

成功:信号量的地址

失败:SEM_FAILED

2)关闭有名信号量

所需头文件:

#include <semaphore.h>

int sem_close(sem_t *sem);
功能:

关闭有名信号量。

参数:

sem:指向信号量的指针。

返回值:

成功:0

失败:-1

3)删除有名信号量文件

所需头文件:

#include <semaphore.h>

int sem_unlink(const char *name);
功能:

删除有名信号量的文件。

参数:

name:有名信号量文件名。

返回值:

成功:0

失败:-1

4)信号量 PV 操作

用法和《POSIX 无名信号量》一样,详情请点此链接。

有名信号量实现进程间互斥功能:

[cpp] view plaincopy
  1. #include<stdio.h>
  2. #include<semaphore.h>
  3. #include<fcntl.h>
  4. #include<unistd.h>
  5. #include<sys/stat.h>
  6. #include<sys/types.h>
  7. void printer(sem_t *sem, char *str)
  8. {
  9. sem_wait(sem);  //信号量减一
  10. while(*str!='\0')
  11. {
  12. putchar(*str);
  13. fflush(stdout);
  14. str++;
  15. sleep(1);
  16. }
  17. printf("\n");
  18. sem_post(sem);  //信号量加一
  19. }
  20. int main(int argc, char *argv[])
  21. {
  22. pid_t pid;
  23. sem_t *sem = NULL;
  24. pid = fork(); //创建进程
  25. if(pid<0){ //出错
  26. perror("fork error");
  27. }else if(pid == 0){ //子进程
  28. //跟open()打开方式很相似,不同进程只要名字一样,那么打开的就是同一个有名信号量
  29. sem = sem_open("name_sem", O_CREAT|O_RDWR, 0666, 1); //信号量值为 1
  30. if(sem == SEM_FAILED){ //有名信号量创建失败
  31. perror("sem_open");
  32. return -1;
  33. }
  34. char *str1 = "hello";
  35. printer(sem, str1); //打印
  36. sem_close(sem); //关闭有名信号量
  37. _exit(1);
  38. }else if(pid > 0){ //父进程
  39. //跟open()打开方式很相似,不同进程只要名字一样,那么打开的就是同一个有名信号量
  40. sem = sem_open("name_sem", O_CREAT|O_RDWR, 0666, 1); //信号量值为 1
  41. if(sem == SEM_FAILED){//有名信号量创建失败
  42. perror("sem_open");
  43. return -1;
  44. }
  45. char *str2 = "world";
  46. printer(sem, str2); //打印
  47. sem_close(sem); //关闭有名信号量
  48. wait(pid, NULL); //等待子进程结束
  49. }
  50. sem_unlink("name_sem");//删除有名信号量
  51. return 0;
  52. }

运行结果如下:

有名信号量实现进程间同步功能(print2 先打印,再到 print1 打印):

print1.c 代码如下:

[cpp] view plaincopy
  1. #include <fcntl.h>           /* For O_* constants */
  2. #include <sys/stat.h>        /* For mode constants */
  3. #include <semaphore.h>
  4. #include <stdio.h>
  5. void print(sem_t *print1, sem_t *print2)
  6. {
  7. int i = 0;
  8. while(1)
  9. {
  10. sem_wait(print1);
  11. i++;
  12. printf("int print1 i = %d\n", i);
  13. sem_post(print2);
  14. }
  15. }
  16. int main(int argc, char **argv)
  17. {
  18. sem_t *print1, *print2;
  19. print1 = sem_open("sem_print1", O_CREAT, 0777, 0);
  20. if(SEM_FAILED == print1)
  21. {
  22. perror("sem_open");
  23. }
  24. print2 = sem_open("sem_print2", O_CREAT, 0777, 1);
  25. if(SEM_FAILED == print2)
  26. {
  27. perror("sem_open");
  28. }
  29. print(print1, print2);
  30. return 0;
  31. }

print2.c 代码如下:

[cpp] view plaincopy
  1. #include <fcntl.h>           /* For O_* constants */
  2. #include <sys/stat.h>        /* For mode constants */
  3. #include <semaphore.h>
  4. #include <stdio.h>
  5. void print(sem_t *print1, sem_t *print2)
  6. {
  7. int i = 0;
  8. while(1)
  9. {
  10. sem_wait(print2);
  11. i++;
  12. printf("in print2 i = %d\n", i);
  13. sleep(1);
  14. sem_post(print1);
  15. }
  16. }
  17. int main(int argc, char **argv)
  18. {
  19. sem_t *print1, *print2;
  20. print1 = sem_open("sem_print1", O_CREAT, 0777, 0);
  21. if(SEM_FAILED == print1)
  22. {
  23. perror("sem_open");
  24. }
  25. print2 = sem_open("sem_print2", O_CREAT, 0777, 1);
  26. if(SEM_FAILED == print2)
  27. {
  28. perror("sem_open");
  29. }
  30. print(print1, print2);
  31. return 0;
  32. }

删除有名信号量示例代码如下:

[cpp] view plaincopy
  1. #include <semaphore.h>
  2. #include <stdio.h>
  3. void sem_del(char *name)
  4. {
  5. int ret;
  6. ret = sem_unlink(name);
  7. if(ret < 0)
  8. {
  9. perror("sem_unlink");
  10. }
  11. }
  12. int main(int argc, char **argv)
  13. {
  14. sem_del("sem_print1"); //删除信号量文件sem_print1
  15. sem_del("sem_print2"); //删除信号量文件sem_print2
  16. return 0;
  17. }

makefile 代码如下:

[plain] view plaincopy
  1. all:
  2. gcc sem_del.c -o sem_del -lpthread
  3. gcc print1.c -o print1 -lpthread
  4. gcc print2.c -o print2 -lpthread
  5. clean:
  6. rm sem_del print1 print2

运行程序时,先把有名信号量删除(sem_del),再分别运行 print1 和 print2:

本教程示例代码下载请点此处。

转自:http://blog.csdn.net/tennysonsky/article/details/46500417

进程同步与互斥:POSIX有名信号量相关推荐

  1. 【Linux系统编程】进程同步与互斥:POSIX有名信号量

    在 POSIX 标准中,信号量分两种,一种是无名信号量,一种是有名信号量.无名信号量一般用于线程间同步或互斥,而有名信号量一般用于进程间同步或互斥.它们的区别和管道及命名管道的区别类似,无名信号量则直 ...

  2. 【Linux系统编程】POSIX有名信号量

    00. 目录 文章目录 00. 目录 01. 概述 02. 相关函数 2.1 创建有名信号量 2.2 关闭有名信号量 2.3 删除有名信号量 2.4 信号量P操作 2.5 信号量V操作 03. 程序示 ...

  3. 进程间通信——POSIX 有名信号量与无名信号量

    原文地址:blogof33.com/post/9/ 前言 在 POSIX 系统中,进程间通信是一个很有意思的话题. POSIX信号量进程是3种 IPC(Inter-Process Communicat ...

  4. Linux——POSIX有名信号量

    有名信号量 作用:主要用于同步线程或进程 头文件:#include <semaphore.h> 创建或打开信号量 /** 输入:const char* name               ...

  5. Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型...

    一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例 ...

  6. Python下进程同步之互斥锁、信号量、事件机制

    链接:https://blog.csdn.net/qq_41964425/article/details/81911343

  7. Linux 下使用 sem_t 有名信号量的注意事项

    一.简介 这种有名信号量的名字由类似"/somename"这样的字符串组成,注意前面有一个正 斜杠,这样的信号量其实是一个特殊的文件,创建成功之后将会被放置在系统的一个特殊的 虚拟 ...

  8. 有名信号量与无名信号量

    有名信号量: 进程 无名信号量: 一般:线程 作用: 用于处理同步互斥 一. 有名信号量 1. 创建或者打开一个有名信号量 sem_open() - man 3 sem_open //初始化并打开一个 ...

  9. 【Linux系统编程】线程同步与互斥:POSIX无名信号量

    信号量概述 信号量广泛用于进程或线程间的同步和互斥,信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问. 编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于 ...

  10. 操作系统之进程管理:11、用信号量机制实现进程同步、互斥、前驱关系

    11.用信号量机制实现进程同步.互斥.前驱关系 思维导图 用信号量机制实现进程同步 用信号量机制实现进程互斥 用信号量机制实现进程的前驱关系 思维导图 用信号量机制实现进程同步 先来看一下什么是进程同 ...

最新文章

  1. 小米android10怎么样,感觉小米10太贵不完美?这些Android旗舰也许就有你的菜!
  2. Servlet中判断浏览器版本的代码
  3. (数据库系统概论|王珊)第三章关系数据库标准语言SQL-第零节:MYSQL环境安装和表的建立以及一些注意事项
  4. mysql索引别名_Mysql索引知识详谈
  5. mysql 两张大表关联_MySQL的DropTable影响分析和最佳实践
  6. 量化中需留意的坑之一
  7. SSH密钥 - 仍然要求输入密码和密码
  8. 【NLP】揭秘马尔可夫模型神秘面纱系列文章(二)
  9. “限时秒杀”活动分析报告
  10. 系统之家装机大师如何制作U盘启动盘?
  11. 医院计算机管理工资,医院绩效管理平台:绩效工资管理系统
  12. 笔记:基于freeradius 3.0的wifi认证
  13. 百度地图商家标注,查询附近3000米内的商家并标到地图上
  14. linux中常用的加密总结--base64编码解码与openssl实现
  15. 18、弱电工程综合布线系统常用的线材及设备图文资料
  16. SPOOL_INTERNAL_ERROR
  17. 四周型文字环绕怎么设置_word艺术字四周型环绕怎么设置
  18. 电话号码对应英文单词 (python)
  19. AlphaFold2源码解析(4)--模型架构
  20. springboot+Quartz整合!!!简单实用

热门文章

  1. linux中LCD之framebuffer设备驱动
  2. skynet 学习笔记-netpack模块(1)
  3. 随笔 --- 深夜反思、重定向
  4. windows Hadoop环境搭建之一---软件准备
  5. flash特效原理:图片滑动放大效果(3)
  6. 思想是精神的种子,改造自己的内心世界
  7. 网管学习日记-三层交换机
  8. 华为hs8145v5如何改桥接_Linksys VelopAX5300和AC3900套装 Mesh组网实战 - 桥接
  9. A - 1 CodeForces - 500A
  10. Docker详解(八)——Docker镜像制作