在 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. js文件中引用其他js文件

    这一个功能的作用是做自己的js包时,可以通过引入一个整体的js文件而引入其他js. 只需要在总体的js加上这一句话 document.write("<script type='text ...

  2. Linux系统调用--getrusage函数详解

    Linux系统调用--getrusage函数详解 功能描述:     获得进程的相关资源信息.如:用户开销时间,系统开销时间,接收的信号量等等;   用法:    #include <sys/t ...

  3. android studio使用中碰到Failure [INSTALL_FAILED_OLDER_SDK] 问题

    第一次使用Android studio开发.直接新建一个默认项目运行出现:Failure [INSTALL_FAILED_OLDER_SDK] , 网上很多人说修改build.gradle中的mins ...

  4. DB2 系统命令与配置参数大全

    主要包括4个部分,分别为: DB2 系统命令 DB2 数据库管理器配置参数 DB2 数据库系统配置参数 DB2 管理服务器(DAS)配置参数DB2 系统命令 dasauto - 自动启动 DB2 管理 ...

  5. SpringBoot中如何使用jpa和jpa的相关知识总结

    jpa常用的注解: 注解 解释 @Entity 声明类为实体或表. @Table 声明表名. @Basic 指定非约束明确的各个字段. @Embedded 指定类或它的值是一个可嵌入的类的实例的实体的 ...

  6. JAVA程序员面试笔试宝典1

    1.为什么Java中有些接口没有任何方法? 这些没有任何方法声明的接口又被称为标识接口,标识接口对于实现它的类没有任何语义上的要求,它仅仅充当一个标识的作用,用来表明它的类属于一个特定的类型. 2.j ...

  7. phpExcel导出excel打不开问题

    用wps和office都打不开,使用旧版的office打开了 出现了一些 warming警告,虽然warming不影响函数的执行,但是php导出excel文件,是header出来的.这个warning ...

  8. react 返回上一页

    import * as React from 'react' import { Layout } from 'antd'; import creatHistory from 'history/crea ...

  9. 洛谷——P3807 【模板】卢卡斯定理

    P3807 [模板]卢卡斯定理 洛谷智推模板题,qwq,还是太弱啦,组合数基础模板题还没做过... 给定n,m,p($1\le n,m,p\le 10^5$) 求 $C_{n+m}^{m}\ mod\ ...

  10. P4817 [USACO15DEC]Fruit Feast 水果盛宴

    P4817 [USACO15DEC]Fruit Feast 水果盛宴 现在Bessie的饱食度为 00 ,她每吃一个橙子,饱食度就会增加 AA :每吃一个柠檬,饱食度就会增加 BB .Bessie还有 ...