首页 > linux进程间通信:system V 信号量

linux进程间通信:system V 信号量

文章目录

        • 概念描述
        • 通信原理
        • 编程接口
        • 使用流程
        • 编程案例

概念描述

  • 英文:semaphore 简称SEM,主要用来进行进程间同步
  • 本质:内核维护的一个正整数,可对其进行各种+/-操作
  • 分类:systemV 信号量、POSIX 有名信号量、POSIX 无名信号量
  • 用途:用来标示系统中可用资源的的个数,协调各个进程有序的访问资源,防止发生冲突
  • P操作:程序在进入临界区之前要对资源进行申请
  • V操作:程序离开临界区后要释放相应的资源

通信原理

  • 类似于房卡,不是单个值,而是一组(实际上是数组)信号量元素构成
  • 将信号量初始设置成一个绝对值
  • 在信号量当前值的基础上加一个数量
  • 在信号量当前值的基础上减去一个数量,降到0以下再去访问会引起阻塞
  • 阻塞进程一直等待其他进程修改该信号量的值,直到恢复正常运行
  • 信号量本身无意义,通常会与一块临界资源(共享内存)关联使用

编程接口

  • 获取信号量ID

    a. 头文件

    b. int semget(key_t key,int nsem, int semflg)

    c. 函数参数:

    • key: 用来表示信号量的键,通常使用值IPC_PRIVATE或者由ftok创建
    • nsem: 信号的数量,所有的信号量放在一个数组里
    • semflg:位掩码,用来设置信号量的权限或者检查一个已有信号量的权限

      IPC_CREAT: 如果找不到指定的key相关联的信号量,创建一个信号量集合

      IPC_EXCL: 若指定了IPC_CREAT且指定key相关联的信号量存在,报EXIST错误

    d. 返回值

    • 成功:返回操作信号量描述符
    • 失败:返回-1
  • 设置信号量

    a. 头文件

    b. int semctl(int semid, int semnum, int cmd ..)

    c. 函数参数:

    • semid: 信号量的描述符,标识符;用于操作信号量
    • semnum: 信号量的数量,所有的信号量放在一个数组内
    • cmd :

      IPC_RMID :删除信号量及相关联的内核smid_ds数据结构

      IPC_STAT: 获取semid_ds的副本

      IPC_SET: 设置semid_ds的数据结构

      GETVAL: 获取信号集中地 semnum个信号量的值

      GETALL: 获取所有信号量的值

      SETVAL: 设置信号集中的第semnum个信号量的值

    d. 函数返回值

    • 成功:根据cmd命令,返回不同的值
    • 失败:-1
  • 信号量P/V操作

    a. 头文件

    b. int semop(int semid,struct sembuf *sops, size_t nsops);

    c. 函数参数:

    • semid :信号的IPC标识符
    • sops: 指向数组的指针,数组中包含了需要执行的操作
      struct sembuf { unsigned short sem_num; // 标识要操作的信号集中的信号量/*sem_op如下信息:a.若大于0 将sem_op的值加到信号量值上b. 若等于0 ,则对信号量进行检查,确定其当前值是否为0,若为0则操作结束;若不为0,则一直阻塞,直到为0结束c. 若小于0,则将信号量值减去sem_op,最后结果大于或等于0,操作立即结束;若最后结果小于0,则当前进程会阻塞*/short sem_op;/*信号操作对标记,SEM_UNDO,IPC_NOWAIT*/short sem_flag;
      }
      
    • nsops:数组的大小

    d. 返回值

    • 成功:根据cmd命令,返回不同的值
    • 失败:-1,并设置errno全局变量

使用流程

  • 使用semget 创建或打开一个信号量集
  • 使用semctl SETVAL 或 SETALL 操作初始化集合中的信号量(其中一个进程操作即可,内核中维护,对其它进程是全局可见的)
  • 使用semop操作信号量的值,多个进程通过多信号量值的操作来表示一些临界资源的获取和释放
  • 当所有进程不再需要信号量集时,使用semctl IPC_RMID 操作删除这个信号量集(其中一个进程操作即可)

编程案例

sem_create.c

#include 
#include 
#include 
#include 
#include #include 
#include 
#include union semnum { int val;struct semid_ds *buf;unsigned short int *array;struct seminfo *__buf;
};int main ()
{ int sem_id;key_t key;if ((key =ftok(".",111)) == -1) { printf("create key failed 
");_exit(-1);}//使用semget 创建或打开一个信号量集if ((sem_id = semget(key,3,IPC_CREAT | 0770)) == -1) { printf("create shm_id failed 
");_exit(-1);} printf("sem_id is :%d
",sem_id);//获取信号量中的值int sem_value;sem_value = semctl(sem_id , 0, GETVAL);printf("sem value is %d
",sem_value);//使用semctl SETVAL 或 SETALL 操作初始化集合中的信号量。通过sem_union设置信号量的值union semnum sem_union;sem_union.val = 2;semctl(sem_id, 0, SETVAL, sem_union);sem_value = semctl(sem_id ,0, GETVAL);printf("sem value after reset is %d
",sem_value);//使用semop操作信号量,对信号量进行pv操作,这里是-1struct sembuf sops,sops2,sops3;sops.sem_num = 0;sops.sem_op = -1;sops.sem_flg = SEM_UNDO;/*sops.sem_num = 1;sops.sem_op = -1;sops.sem_flg = SEM_UNDO;sops.sem_num = 2;sops.sem_op = -1;sops.sem_flg = SEM_UNDO;*/if( -1 == (semop(sem_id,&sops, 1)) ) { printf("semop set failed 
");_exit(-1);}sem_value = semctl(sem_id, 0, GETVAL);printf("sem value after semop is %d
",sem_value);sleep(30);semctl(sem_id, 0 ,IPC_RMID);return 0;
}

最终的输出如下:

sem_id is :524314
sem value is 0
sem value after reset is 2
sem value after semop is 1

更多相关:

  • 空闲态:这时候手机只能使用一路信号,应该是最强的那一路。手机在空闲态时不断地搜索各个导频的强度,如果搜到比当前使用的导频更强的,那么它就自发的进行切换。这个切换的过程是手机自发的过程,不需要基站的参与。业务态:手机最多可以使用3路导频信号,并且将这3路导频信号进行最大比合并,也就是说将3个信号合并成更强的信号。如果手机测量到有更强的导...

  • 信号量概念理解 信号量本质上 是一个计数器,用来统计临界资源申请资源的个数。其中的二元信号量的 值是0或者是1,即是要么是有,要么是无。信号量本身也是临界资源,所以一定要保证其原子性。信号量的工作原理:两个进程共享一个信号量sv,一个进程访问的sv的时候,进行的是P操作即是减1操作,开始的时候信号量是1,它得到信号量进入临界资源。当...

  • osi七层协议 互联网协议按照功能不同分为osi七层或tcp/ip五层或tcp/ip四层 每层运行常见的物理设备 我们将应用层,表示层,会话层并作应用层,从tcp/ip五层协议的角度来阐述每层的由来与功能,搞清楚了每层的主要协议 就理解了整个互联网通信的原理。 首先,用户感知到的只是最上面一层应用层,自上而下每层都依赖于下一层,所...

  • 文章目录概念描述编程接口注意事项编程案例信号量基本接口使用案例信号量父子进程间通信信号量实现 两进程之间通信 概念描述 英文:semaphore 简称SEM,主要用来进行进程间同步本质:内核维护的一个正整数,可对其进行各种+/-操作分类:systemV 信号量、POSIX 有名信号量、POSIX 无名信号量用途:用来标示系统...

  • 生产者和消费者模型: 有若干个缓冲区,生产者不断向里填数据,消费者不断从中取数据两者不冲突的前提: 缓冲区有若干个,且是固定大小,生产者和消费者各有若干个生产者向缓冲区中填数据前需要判断缓冲区是否满,满了则等待,直到有空间消费者从缓冲区中取数据前需要判断缓冲区是否为空,空了则等待,直到缓冲区有数据在某一时刻,缓冲区中只允许有一个操作...

  • 关于信号量和共享内存的相关描述已经在前几篇提到过; 信号量:即内核维护的一个正整数,可以使用内核提供的p/v接口进行该正整数的+/-操作,它主要用来表示系统中可用资源的个数,协调各个进程有序访问资源,防止发生冲突共享内存:操作系统从运行中的进程拥有的3G用户空间中提供一段用户态可以直接访问的内存块,并且该内存区域可以被其他进程共享...

  • 一次手贱更新了上面这个驱动,结果: Fn+F2/F3不能控制亮度win+X弹出来的下面这个窗口“显示器亮度”不见了 电源选项里面底部“屏幕亮度”也不见了 我研究了三天,各种骚操作都试过了,最后找到解决方案: win+R 输入 devmgmt.msc 回车,按照下图操作,瞬间亮度恢复正常 ...

  • 第一种:需要刷新当前页面重复执行的操作——使用场景:刷点击率 、秒杀活动、抢沙发   //自动化循环操作方法 var doLoop = function (dom) {dom || (dom = document);//这里写循环操作的代码dom.querySelector("sel").innerHTML = "舒工的骚操作!!...

  • Ubuntu常用操作外观操作修改应用icon图标终端美化内存管理内存查询分区管理日志清理操作执行自动执行多条命令...

  • 文章目录前言工业级 LRU Cache1. 基本架构2. 基本操作2.1 insert 操作2.2 高并发下 insert 的一致性/性能 保证2.3 Lookup操作2.4 shard 对 cache Lookup 性能的影响2.4 Erase 操作2.5 内存维护3. 优化...

  • 最近利用vim做一些文本处理时 发现vim 支持的键盘宏是一个好东西啊,高效优雅得处理大量需要重复性操作的文本,让人爱不释手!!! 希望接下来对键盘宏的分享能够实际帮助到大家。 后文中描述的一些vim操作会汇集成指令字符串,方便大家参考。 1. 场景描述 在分享键盘宏之前,先看这样一个文本操作需求: 对如下文本增加ma...