在 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 无名信号量》一样,详情请点此链接。

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

  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 代码例如以下:

  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 代码例如以下:

  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. }

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

  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
plain
copy

  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. 一起talk C栗子吧(第一百回:C语言实例--使用信号量进行进程间同步与相互排斥一)

    各位看官们.大家好,上一回中咱们说的是进程间同步与相互排斥的样例,这一回咱们说的样例是:使用信号量进行进程间同步与相互排斥. 闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,信号量是由著名 ...

  2. 多线程相互排斥--mutex(二)

    不知道大家对多线程或多进程间的同步相互排斥的控制机制了解的怎么样,事实上有非常多种方法能够实现这个目的,可是这些方法事实上由4种最主要的方法实现.这4种最主要的方法详细定义例如以下:在这有讲得不正确的 ...

  3. android NDK编程:使用posix多线程与mutex相互排斥同步

    MainActivity.java 调用原生方法 posixThreads(int threads, int iterations) 启动线程 package com.apress.threads; ...

  4. Linux互斥和同步应用程序(一):posix线程和线程之间的相互排斥

    [版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流.请勿用于商业用途] 有了进程的概念,为何还要使用线程呢? 首先,回 ...

  5. Linux相互排斥与同步应用(三):posix线程实现单个生产者和单个消费者模型

            [版权声明:尊重原创.转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu.文章仅供学习交流,请勿用于商业用途]         在第一节说到了 ...

  6. Linux同步与相互排斥应用(零):基础概念

    [版权声明:尊重原创,转载请保留出处:blog.csdn.net/shallnet 或 .../gentleliu,文章仅供学习交流,请勿用于商业用途]         当操作系统进入多道批处理系统时 ...

  7. Linux下进程的同步相互排斥实例——生产者消费者

    linux下的同步和相互排斥 Linux sync_mutex 看的更舒服点的版本号= = https://github.com/Svtter/MyBlog/blob/master/Linux/pth ...

  8. 【C/C++多线程编程之六】pthread相互排斥量

    多线程编程之线程同步相互排斥量       Pthread是 POSIX threads 的简称,是POSIX的线程标准.          Pthread线程同步指多个线程协调地,有序地同步使用共享 ...

  9. Linux程序设计学习笔记----多线程编程线程同步机制之相互排斥量(锁)与读写锁

    相互排斥锁通信机制 基本原理 相互排斥锁以排他方式防止共享数据被并发訪问,相互排斥锁是一个二元变量,状态为开(0)和关(1),将某个共享资源与某个相互排斥锁逻辑上绑定之后,对该资源的訪问操作例如以下: ...

随机推荐

  1. mongo 3.4分片集群系列之六:详解配置数据库

    这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mongo 3.4分片集群系列之三:搭建 ...

  2. Detectron-MaskRCnn:Mask判别和获取前向Mask的标签

    对于FCN-SceneParse网络,最后卷积生成N个类别的maps,每个Map都得到图像所有点的单类概率.MaskRCNN的结构与FCN不相同. 参考三个文章: Detectron总结1:Blob的 ...

  3. Filesystem Hierarchy Standard (Unix, Linux etc)

    http://www.pathname.com/fhs/ /boot -- Static files of the boot loader Purpose: contains everything r ...

  4. jQuery 遍历 - children() 方法

    jQuery 遍历参考手册 实例 找到类名为 "selected" 的所有 div 的子元素,并将其设置为蓝色: $("div").children(" ...

  5. Extjs定时操作

    查看api可知: // 启动一个简单的时钟任务,每秒执行一次更新一个 div var task = { run: function(){ Ext.fly('clock').update(new Dat ...

  6. Re0:DP学习之路 01背包如何打印路径?

    伪代码 用二维数组记录,如果出现可以转移的dp那么记录bk[当前体积][装的物品]=1 输出的时候倒推,如果存在连通的边那么输出并且总共的体积减去输出的体积 代码(uva-624,目前wa不明所以,网 ...

  7. 记VS2008安装及使用及卸载的艰辛历程!!!(2018/11/6-2018/11/14)

    此文为了纪念我对VS2008“孜孜不倦的”无数次的安装及卸载,以及解决使用过程中出现的问题所花费的人力物力和财力!成功之后再作补充.

  8. CCF201609-2 火车购票 java(100分)

    试题编号: 201609-2 试题名称: 火车购票 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 请实现一个铁路购票系统的简单座位分配算法,来处理一节车厢的座位分配. 假设一 ...

  9. Glossary in Turbulence

    Table of Contents 1. Concepts/Glossary 1.1. Turbulent eddy viscosity ,μt 1.2. Turbulent kinetic ener ...

  10. 腾讯云:基于 Ubuntu 搭建 VNC 远程桌面服务

    基于 Ubuntu 搭建 VNC 远程桌面服务 前言 任务时间:5min ~ 10min 必要知识 本教程假设您已学习以下 Ubuntu 基本操作: 连接 SSH 执行命令 编辑文件 如果还没有掌握 ...