linux 信号量_SystemV IPC通信信号量
1信号量的认知
Linux 中用到的信号量有 3 种:ststem-V 信号量、POSIX 有名信号量和 POSIX 无名信号量)。他们虽然有很多显著不同的地方,但是最基本的功能室一致的:用来表征一种资源的数量,当多个进程或者线程争夺这些稀缺资源的时候,信号量用来保证他们合理地、秩序地使用这些资源,而不会陷入逻辑谬误之中。
用一个例子来说明什么是“旗语”——红绿灯, 一个繁忙的十字路口,稀缺资源就是通过十字路口的权限,为了避免撞车规定每次只能是对开方向的车通过路口不能转弯),此时另外两个方向的车必须停下来等待,直到红绿灯变换为止
一些基本概念如下:
1,多个进程或线程有可能同时访问的资源(变量、链表、文件等等)称为共享资源,也叫临界资源(critical resources)。
2,访问这些资源的代码称为临界代码,这些代码区域称为临界区(critical zone)。
3,程序进入临界区之前必须要对资源进行申请,这个动作被称为 P 操作,这就像你要把车开进停车场之前,先要向保安申请一张停车卡一样,P 操作就是申请资源,如果申请成功,资源数将会减少。如果申请失败,要不在门口等,要不走人。
4,程序离开临界区之后必须要释放相应的资源,这个动作被称为 V 操作,这就像你把车开出停车场之后,要将停车卡归还给保安一样,V 操作就是释放资源,释放资源就是让资源数增加。所有一起访问共同临界资源的进程都必须遵循以上游戏规则,否则大家就都乱套了,但是值得注意的是:这些规则是自愿的,如果有进程就是胡来——在访问资源之前不申请,那么将会可能导致逻辑谬误,就像开车压死保安直接撞进停车场一样,虽然于情于理都不可以,物理上阻止不了这种行为。
2相关API
创建信号量时,还受到以下系统信息的影响:
1,SEMMNI:系统中信号量的总数最大值。
2,SEMMSL:每个信号量中信号量元素的个数最大值。
3,SEMMNS:系统中所有信号量中的信号量元素的总数最大值。
Linux 中,以上信息在/proc/sys/kernel/sem 中可查看。
使用以上函数接口需要注意以下几点:
1,信号量操作结构体的定义如下:
struct sembuf{unsigned short sem_num; /* 信号量元素序号(数组下标) */short sem_op; /* 操作参数 */short sem_flg; /* 操作选项 */};
请注意:信号量元素的序号从 0 开始,实际上就是数组下标。
2,根据 sem_op 的数值,信号量操作分成 3 种情况:
A) 当 sem_op 大于 0 时:进行 V 操作,即信号量元素的值(semval)将会被加上 sem_op 的值。如果 SEM_UNDO 被设置了,那么该 V 操作将会被系统记录。V 操作永远不会导致进程阻塞。
B) 当sem_op等于0时:进行等零操作,如果此时semval恰好为0,则semop( )立即成功返回,否则如果 IPC_NOWAIT 被设置,则立即出错返回并将 errno 设置为EAGAIN,否则将使得进程进入睡眠,直到以下情况发生:
B1) semval 变为 0。
B2) 信号量被删除。(将导致 semop( )出错退出,错误码为 EIDRM)
B3) 收到信号。(将导致 semop( )出错退出,错误码为 EINTR)
C) 当 sem_op 小于 0 时:进行 P 操作,即信号量元素的值(semval)将会被减去 sem_op 的绝对值。如果 semval 大于或等于 sem_op 的绝对值,则 semop( )立即成功返回,semval 的值将减去 sem_op 的绝对值,并且如果 SEM_UNDO 被设置了,那么该 P 操作将会被系统记录。如果 semval 小于 sem_op 的绝对值并且设置了IPC_NOWAIT,那么 semop( )将会出错返回且将错误码置为 EAGAIN,否则将使得进程进入睡眠,直到以下情况发生:
C1) semval 的值变得大于或者等于 sem_op 的绝对值。
C2) 信号量被删除。(将导致 semop( )出错退出,错误码为 EIDRM
C3) 收到信号。(将导致 semop( )出错退出,错误码为 EINTR)
3代码展示
sem_p.c(进行减操作)
#include #include #include #include #include union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ };int main(void){ key_t key; int sem_id; int retval; //获取一个IPC对象 key = ftok(".", 1); if(key == -1) { perror("获取IPC对象的key值出错"); goto get_ipc_key_err; } //获得信号量ID,其中如果信号量没有则创建出来,1代表创建1个信号量 sem_id = semget( key, 1, IPC_CREAT|0644); if(sem_id == -1) { perror("获取信号量出错"); goto get_semid_err; } union semun semarg;//这个是semctl函数说明的,如果第四个参数需要定义的一个共用体 semarg.val = 0;//设置信号量初值为0 /* 设置信号量初值 sem_id:设置的信号量ID 0:设置这个信号量当中的第几个信号量 SETVAL:命令,设置单个信号量的初值 semarg:设置的共用体 */ semctl(sem_id, 0, SETVAL, semarg); struct sembuf op_sem; op_sem.sem_num = 0;//第几个信号量 op_sem.sem_op = -1;//-1操作 op_sem.sem_flg = 0;//按照默认的信号量操作(当减到即将成为一个负数的时候陷入睡眠) //进行减操作 /* sem_id:操作的信号量 op_sem:做何种操作 1:一次性操作1个信号量 */ semop( sem_id, &op_sem, 1); printf("减操作成功\n"); //删除整个信号量集合 //semctl(sem_id, 0, IPC_RMID); return 0;get_semid_err:get_ipc_key_err: return -1;}
sem_v.c(进行加操作)
#include #include #include #include #include union semun { int val; /* Value for SETVAL */ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */ unsigned short *array; /* Array for GETALL, SETALL */ struct seminfo *__buf; /* Buffer for IPC_INFO (Linux-specific) */ };int main(void){ key_t key; int sem_id; int retval; //获取一个IPC对象 key = ftok(".", 1); if(key == -1) { perror("获取IPC对象的key值出错"); goto get_ipc_key_err; } //获得信号量ID,其中如果信号量没有则创建出来,1代表创建1个信号量 sem_id = semget( key, 1, IPC_CREAT|0644); if(sem_id == -1) { perror("获取信号量出错"); goto get_semid_err; } struct sembuf op_sem; op_sem.sem_num = 0;//第几个信号量 op_sem.sem_op = 1;//+1操作 op_sem.sem_flg = 0;//按照默认的信号量操作(当减到即将成为一个负数的时候陷入睡眠) //进行加操作 /* sem_id:操作的信号量 op_sem:做何种操作 1:一次性操作1个信号量 */ semop( sem_id, &op_sem, 1); //删除整个信号量集合 //semctl(sem_id, 0, IPC_RMID); return 0;get_semid_err:get_ipc_key_err: return -1;}
记录点点滴滴的笔记欢迎关注,共同学习
小浩笔记
linux 信号量_SystemV IPC通信信号量相关推荐
- python并发编程之semaphore(信号量)_python 之 并发编程(守护进程、互斥锁、IPC通信机制)...
9.5 守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就立即终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic process ...
- Linux进程间通信第四讲 标准IPC之信号量集
目录 4.3信号量集 4.3.1 概念和原理 4.3.2 使用 4.3信号量集 4.3.1 概念和原理 (不是用于进程间传递数据.而是用于进程间访问控制) 信号量集是一个信号量的集合,可以存放多个信号 ...
- linux进程间通信:system V 信号量 生产者和消费者模型编程案例
生产者和消费者模型: 有若干个缓冲区,生产者不断向里填数据,消费者不断从中取数据 两者不冲突的前提: 缓冲区有若干个,且是固定大小,生产者和消费者各有若干个 生产者向缓冲区中填数据前需要判断缓冲区是否 ...
- linux 内核信号量与用户态信号量(system v,信号量在Linux多线程机制中的应用
[摘 要]本文以信号量原理为基础,重点阐述信号量在Linux多线程同步机制中的实现特色. [关键词]信号量:Linux:多线程:同步 1 信号量 1965年E. W. Dijkstra首次提出信号量的 ...
- 深刻理解 Linux 进程间七大通信(IPC)
前言 网络编程是 Linux C/C++的面试重点,今天我就来聊一聊进程间通信的问题,文章末尾列出了参考资料,希望帮助到大家. 篇幅有点长,希望大家耐心阅读. Linux 下的进程通信手段基本上是从 ...
- linux进程间通信:system V 信号量
文章目录 概念描述 通信原理 编程接口 使用流程 编程案例 概念描述 英文:semaphore 简称SEM,主要用来进行进程间同步 本质:内核维护的一个正整数,可对其进行各种+/-操作 分类:syst ...
- 专题 13 IPC之信号量
1.概述 信号量是一种计数器,用来控制对多个进程共享的资源所进行的访问.它们常被用做一个锁机制. 2.相关数据结构与函数 信号量数据结构: structsemun { intval;//当执行SETV ...
- Linux进程间通信三 System V 信号量简介与示例
1. System V信号量简介 SystemV信号量主要用于解决生产者和消费者问题,一个信号量能够控制多个资源,说它是信号量集也不为过. 2. API接口介绍 2.1 创建或打开信号量集 #incl ...
- Linux内核信号量:二值信号量/互斥信号量,计数信号量,读写信号量
<semaphore信号量:一个简单的示例程序>用户态程序 目录 概念 应用场景 使用方法 内核信号量的构成 信号量的API 初始化 PV操作 获取信号量(P) 释放内核信号量(V) 补充 ...
- Linux下多线程编程中信号量介绍及简单使用
在Linux中有两种方法用于处理线程同步:信号量和互斥量. 线程的信号量是一种特殊的变量,它可以被增加或减少,但对其的关键访问被保证是原子操作.如果一个程序中有多个线程试图改变一个信号量的值,系统将保 ...
最新文章
- A - 排名 HDU - 1236 sort(cmp)
- If-Modified-Since和If-None-Match
- 反浏览器指纹追踪(反浏览器指纹追踪技术)
- 嵌入式开发概述(树莓派介绍)
- 编写函数判断一个数是否是回文数_程序员面试金典 - 面试题 01.04. 回文排列
- python多目标优化_多目标优化算法(四)NSGA3(NSGAIII)论文复现以及matlab和python的代码...
- 一文初探Tensorflow高级API使用(初学者篇)
- Linux 文件传输
- linux系统启动后卡在笑脸符号,【转】Linux中的特殊符号
- 光影精灵usb安装linux,惠普光影精灵5笔记本怎么装win10系统(uefi+gpt)
- DES 加密解密方法
- 阿里云ecs服务器买完后可以更换操作系统么?
- vscode编译Window c++程序缺少vc运行库解决方法
- # CF #808 Div.2(A - C)
- CAS单点登录(SSO)介绍及部署
- 面向过程、面向对象 的模型和方法
- java roll_Java Calendar roll()用法及代碼示例
- Chrome 超强生产力工具 Omni
- 上海迪士尼度假区将推出一系列节庆活动和全新“萌聚达菲月”
- 从《羞羞的铁拳》中嗅到的
热门文章
- git pull冲突:commit your changes or stash them before you can merge.
- ubuntu备份与恢复
- android sid如何验证有效性,使用RMAN验证备份的有效性
- Docker 快速安装教程
- springcloud之eureka集群搭建
- servlet 之forward和sendRedirect跳转
- JavaScript编写计算器-《JavaScript王者归来》读书笔记1
- C++ 数组动态分配
- 携程基于云的软呼叫中心及客服平台架构实践\n
- Android UsageStatsService(应用使用统计服务)的学习与调研