1.特点:  信号灯集,是控制访问临界资源

信号灯(semaphore),也叫信号量。它是不同进程间或一个给定进程内部不同线程间同步的机制System V的信号灯是一个或者多个信号灯的一个集合(允许对集合中的多个计数信号灯进行同时操作)。其中的每一个都是单独的计数信号灯。而Posix信号灯指的是单个计数信号灯

2.信号灯种类:
  posix有名信号灯
  posix基于内存的信号灯(无名信号灯)(线程)
  System V信号灯(IPC对象)(信号灯的值就是代表资源的数量)

3.创建步骤:
  1)产生key值
  2)创建信号灯集
  3)初始化信号灯(对信号灯集中的每个信号灯进行初始化)
  4)信号灯的P-V操作
  5)删除信号灯集

4.相关函数:
  1)int semget(key_t key, int nsems, int semflg);
    功能:创建/打开信号灯
    参数:key:ftok产生的key值(和信号灯关联的key值)
         nsems:信号灯集中包含的信号灯数目
         semflg:信号灯集的访问权限,通常为IPC_CREAT |0666
    返回值:成功:信号灯集ID ; 失败:-1

  2)int semop ( int semid, struct sembuf *opsptr, size_t nops);
    功能:对信号灯集合中的信号量进行P - V操作
    参数:semid:信号灯集ID
         struct sembuf {
        short sem_num; // 要操作的信号灯的编号
        short sem_op; // 0 : 等待,直到信号灯的值变成0 // 1 : 释放资源,V操作 // -1 : 分配资源,P操作 
        short sem_flg;  // 0(阻塞),IPC_NOWAIT, SEM_UNDO
         };//对某一个信号灯的操作,如果同时对多个操作,则需要定义这种结构体数组

         nops: 要操作的信号灯的个数 ,1个
    返回值:成功 :0 ; 失败:-1

      用法:semop(semid, &mysembuf, 1);
      申请资源 P操作:
        mysembuf.sem_num = 0;
        mysembuf.sem_op = -1;
        mysembuf.sem_flg = 0;
      释放资源 V操作:
        mysembuf.sem_num = 0;
        mysembuf.sem_op = 1;
        mysembuf.sem_flg = 0;

3)int semctl ( int semid, int semnum, int cmd…/*union semun arg*/);
  功能:信号灯集合的控制(初始化/删除)
  参数:semid:信号灯集ID
       semnum: 要操作的集合中的信号灯编号
       cmd:
      GETVAL:获取信号灯的值,返回值是获得值
      SETVAL:设置信号灯的值,需要用到第四个参数:共用体
      IPC_RMID:从系统中删除信号灯集合
  返回值:成功 0 ; 失败 -1

  用法:
  初始化:semctl(semid, 0, SETVAL, mysemun);
  需要在程序中定义共用体
  获取信号灯值:semctl(semid, 0, GETVAL);
  删除信号灯集:semctl(semid, 0, IPC_RMID);

例子: 简单对信号灯的操作(多值信号灯)

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/types.h>
  4. #include <sys/ipc.h>
  5. #include <sys/sem.h>
  6. #include <errno.h>
  7.  
  8. int semid; //信号灯集id, 通过这个id 操作这个信号灯集,在不同进程中,操作同一个信号灯集的id
  9. union semnum
  10. {
  11. int val;
  12. };
  13.  
  14. union semnum mynum;
  15. struct sembuf mybuf; //定义操作信号灯的结构
  16.  
  17. //参数 信号灯集id 和 是哪个信号灯
  18. void sem_p(int semid, unsigned short num) //P操作函数
  19. {
  20. mybuf.sem_num = num; //第一个信号灯,(信号灯编号)
  21. mybuf.sem_op = -; //进行P操作, 为 1 时表示V操作
  22. mybuf.sem_flg = ; //阻塞
  23. semop(semid, &mybuf, ); //最后一个参数,表示操作信号灯的个数
  24. }
  25.  
  26. //参数 信号灯集id 和 是哪个信号灯
  27. void sem_v(int semid, unsigned short num) //V操作函数
  28. {
  29. mybuf.sem_num = num;
  30. mybuf.sem_op = ; //1 表示V 操作
  31. mybuf.sem_flg = ; //阻塞
  32. semop(semid, &mybuf, ); //操作的 mybuf 全部变量信号灯集
  33. }
  34.  
  35. int main(int argc, const char *argv[])
  36. {
  37. key_t key;
  38. key = ftok("app",'m');//获取唯一的 key
  39. if(key < )
  40. {
  41. perror("fail fptk ");
  42. exit();
  43. }
  44. //int semget(key_t key, int nsems, int semflg);
  45. //IPC_EXCL | IPC_CREAT 信号灯不存在就创建
  46. semid = semget(key, , IPC_CREAT|IPC_EXCL|); //创建信号灯,IPC_EXCL 问信号灯存不存在
  47. if(semid < )
  48. {
  49. if(errno == EEXIST)//存在时,只需要打开即可
  50. {
  51. semid = semget(key,,); //打开信号灯
  52. }
  53. else
  54. {
  55. perror("semget fail ");
  56. }
  57. }
  58. else
  59. {
  60. // int semctl(int semid, int semnum, int cmd, ...);
  61. mynum.val = ; //设置信号灯值
  62. semctl(semid,,SETVAL,mynum); //初始化 0 号信号灯,此处使用共用体设置信号灯值,初始化完成后可以继续给下一个信号灯设置值
  63.  
  64. mynum.val = ; //设置信号灯值
  65. semctl(semid,,SETVAL,mynum); //初始化 1 号信号灯,把设置的信号灯值给1号信号灯
  66. }
  67. sem_p(semid, ); //对semid 指向的信号灯集,中0号信号灯进行P操作
  68. sem_p(semid, ); //对semid 指向的信号灯集,中0号信号灯进行P操作
  69. sem_p(semid, ); //对semid 指向的信号灯集,中0号信号灯进行P操作
  70. printf("%d\n",semctl(semid, , GETVAL)); //上面对 0 信号灯初始值 10 进行流三次P 操作,此时应该为 7
  71. printf("%d\n",semctl(semid, , GETVAL)); //没有对 1 信号灯操作,其值不变为 5
  72. putchar();
  73.  
  74. sem_v(semid,);
  75. printf("%d\n",semctl(semid, , GETVAL)); //上面对 1 信号灯 V 操作,其值变为 6
  76.  
  77. semctl(semid,,IPC_RMID);//删除信号灯
  78. return ;
  79. }

测试:对于多值信号灯可以进行多次P操作

Linux 进程间通信 信号灯集的更多相关文章

  1. Linux进程间通信:IPC对象——信号灯集详解

    作者:倪老师,华清远见嵌入式学院讲师. 一.信号灯概述 信号灯与其他进程间通信方式不大相同,它主要提供对进程间共享资源访问控制机制.相当于内存中的标志,进程可以根据它判定是否能够访问某些共享资源,同时 ...

  2. <转>Linux环境进程间通信--信号灯(四)

    http://www.ibm.com/developerworks/cn/linux/l-ipc/part4/ 一.信号灯概述 信号灯与其他进程间通信方式不大相同,它主要提供对进程间共享资源访问控制机 ...

  3. 【转】 Linux进程间通信

    一.进程间通信概述进程通信有如下一些目的:A.数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间B.共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别 ...

  4. (转载)Linux进程间通信

    (在学习linux进程通信,看到一篇很好的文章,转载过来,原文地址是http://www.cnblogs.com/linshui91/archive/2010/09/29/1838770.html) ...

  5. Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存

    Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存 参考:<linux编程从入门到精通>,<Linux C程序设计大全>,<unix环境高级编程> ...

  6. linux进程间通信-(转自 临水)

    一.进程间通信概述进程通信有如下一些目的:A.数据传输:一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M字节之间B.共享数据:多个进程想要操作共享数据,一个进程对共享数据的修改,别 ...

  7. Linux进程间通信(一): 信号 signal()、sigaction()

    一.什么是信号 用过Windows的我们都知道,当我们无法正常结束一个程序时,可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?同样的功能在Linux上是通过生成信号和捕获信号来实现的,运行中 ...

  8. Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()

    我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,也可以屏蔽某些信号,使其不能传递给进程.那么我们应该如何设定我 ...

  9. linux进程间通信-概述

    一 进程间通信有如下的目的: 1.数据传输,一个进程需要将它的数据发送给另一个进程,发送的数据量在一个字节到几M之间:2.共享数据,多个进程想要操作共享数据,一个进程对数据的修改,其他进程应该立刻看到 ...

随机推荐

  1. Python运算

    逻辑运算 指数运算 整除 所以,我们来做个运算吧~ 用raw_input()可以从键盘上读取输入,raw_input()中的字符串会在屏幕上面打印出来 用int()转只因为Python默认都是以str ...

  2. vue - blog开发学习1

    1.安装vue-cli vue intall -g vue-cli 2.创建项目 vue init webpack nblog 3.按提示要求配置项目 ? Project name nblog ? P ...

  3. c# 盖尔-沙普利算法的改进

    盖尔-沙普利算法 “盖尔-沙普利算法”(the Gale-Shapley algorithm),也被称为“延迟接受算法”(deferred-acceptance algorithm),简称“GS算法” ...

  4. ERROR 1290 (HY000): Unknown error 1290

    如有需要可以加我Q群[308742428]大家一起讨论技术,提供有偿服务. 后面会不定时为大家更新文章,敬请期待. 喜欢的朋友可以关注下. 记录一次在连接数据库报的一个错误信息: 原因是MySQL正使 ...

  5. Stm32 控制1.44寸液晶显示图片 基于stm32f051k8u6

    在线图片转BMP格式:https://app.xunjiepdf.com/img2bmp 一.使用工具对图片生成字符数组 1. 使用1.44寸的液晶其像素是128*128的16位真彩,则需要把图片调整 ...

  6. MOS管知识大集

    MOS管 增强型:就是UGS=0V时漏源极之间没有导电沟道,只有当UGS>开启电压(N沟道)或UGS<开启电压(P沟道)才可能出现导电沟道.耗尽型:就是UGS=0V时,漏源极之间存在导电沟 ...

  7. hbase GC优化

    编辑配置文件 编辑 hbase-env.sh   export HBASE_OPTS="$HBASE_OPTS -XX:+UseCompressedOops -XX:+UseParNewGC ...

  8. 前端用vue,后端需要nodejs吗?

    其实用脚趾头想想也知道:后端用不用node,和前端用不用vue,二者完全没关系. 那为何用vue和vue插件开发前端的时候,经常需要各种npm install呢?为何要在本地安装node环境? 本地需 ...

  9. matlab filtfilt 函数

    紧接上一篇,简单分析matlab中的非常好用的 filtfilt 函数,一款零相移滤波函数. 其matlab中的语法如下: y = filtfilt(data,x);1非常简单,不是一般的简单!然而, ...

  10. Mongodb导入本地数据(.dat)到仓库(window)

    借鉴文章,完成了数据文件导入到Mongodb, 尊重作者版权:https://blog.csdn.net/weixin_44198965/article/details/100022616 1.找到你 ...