Linux - 进程间通信 - 信号量
一、概念
简单来讲,信号量是一个用来描述临界资源的资源个数的计数器。
信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件、外部设备等)来实现进程间通信,
他本身更只是一种外部资源的标识。信号量在此过程中负责数据操作的同步、互斥等功能。
当请求 一个使用信号量来表示 的资源时,进程需要先读取信号量的值来判断资源是否可用。大于0,资源可以请求;等于0,无资源可用,
进程会进入睡眠状态直至资源可用。
当进程不再使用一个使用信号量控制的共享资源时,信号量的值+1,对信号量的值进行的增减都是原子操作,这是由于信号量的主要作用
是维护资源的互斥或多进程的同步访问。而在信号量的创建及初始化上,不能保证操作均为原子性。
原子操作:
所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另
一个线程)。共享数据(全局变量或堆变量)的自增(++)操作在多线程环境下会出现错误是因为这个操作(一条c语句)被编译为汇编代码后不
止一条指令,因此在执行的时候可能执行了一半就被调度系统打断,去执行别的代码。
我们把单指令的操作称为原子的(Atomic),因为无论如何,单条指令的执行是不会被打断的。
总而言之,原子操作的状态是要么不做,要么做并且完成,没有做了但没有完成这种状态。
二、为什么要使用信号量
为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,他可以通过生成并使用令牌来授权,在任意时刻只能
由一个执行线程访问代码的临界区域。临界区域是指执行数据更新的代码需要独占的执行。而信号量就可以提供这样的一 种访问机制让一个临界区
域同一时间只有一个线程访问它,也就是说信号量使用来协调进程对共享资源的访问的。其中共享内存的使用就要用到信号量。
三、信号量的工作原理:
我们这里讲的是二元信号量:
二元信号量(Binary Semaphore)是最简单的一种锁,它只用两种状态:占用与非占用。它适合只能被唯一一个线程访问的资源。当二元信号量
处于非占用状态时,第一个试图获取该二元信号量的线程会获得该锁,并将二元信号量置为占用状态,此后其他的所有试图获取该二元信号量的线程将会
等待,知道该锁被释放。
由于信号量只能进行两种操作:等待和发送信号,即 P(sv)和 V(sv)。它们的行为是这样的:
P(sv):若sv值大于0,就给它减1,;若他的值为0,就挂起该进程的执行
V(sv)如果有其他进程因等待sv而被挂起,就让他恢复运行;如果没有进程因等待而被挂起,那就给他们加1。
举个例子:
就是两个进程共享信号量sv,一旦其中一个进程执行了P(sv)操作,他将得到信号量,并可以进入临界区,使sv减1,。而第二个进程将被阻止进入临界
区,因为当它试图执行P(sv)时,sv为0,他会被挂起以等待第一个进程离开临界区并执行V(sv)释放信号量,这时第二个进程就可以恢复运行。
四、相关函数
1、创建信号量集(每次创建一个多多个信号量)
头文件:#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
函数原型:int semget(key_t key,int nsems,int semflg);
返回值:调用成功返回IPC标识符,调用失败返回-1;
参数:
key:所创建或打开信号量集的键值,也可以有函数 ftok 生成(不同于fork)
nsems:表示创建的信号量集中信号量的个数,该参数只在创建信号量集时有效
semflg: IPC_CREAT:如果IPC存在,则打开它,若不存在,则创建IPC资源。
IPC_EXCL:不能单独使用,没有意义;当与IPC_CREAT搭配使用时表示:若IPC不存在则创建IPC资源,若存在,则产生错 误。二者一 起使用用来保证所得的对象是新建的,而不是打开已有的对象。
2、执行在信号量集上的控制操作
头文件:#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
函数原型:int semctl(int semid,int semnum,int cmd, …);
返回值:调用成功返回一个正数,调用失败返回-1。
参数:semid:信号量集IPC标识符,因为信号量一般是作为一个信号量集使用的,而不是一个单独的信号量。所以在信号量集的操作中,不但要知道IPC关键字值,也要知道信号量集中的具体的信号量。
semnum:操作信号在信号量集中的编号
cmd:系统设置了三种操作:
IPC_STAT:读取一个信号量集的数据结构semid_ds,并将其储存在semun中的buf参数。
IPC_SET:设置信号量集的数据结构senid_ds中的元素ipc_perm,其值取自semun中的buf参数。
IPC_RMID:将信号量集从内存中删除。
3、操作信号量
头文件:#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
函数原型:int semop(int semid,struct sembuf * sops,unsigned nsops);
返回值:调用成功返回0,调用失败返回-1。
参数:semid:信号量集标识码
nsops:信号结构的数量,恒大于或等于1.
sops:指向寻出信号操作结构的数组指针,信号操作结构的原型如下:
struct sembuf
{
unsigned short sem_num; //操作信号在信号量集中的编号,第一个编号为0.
short sem_op;
short sem_flg; //信号操作标志,可能的选择有两种:
IPC_NOWAIT:对信号的操作不能满足时,semop()不会阻塞,并立即返回,同时设定错误信息;
SEM_UNDO:程序结束时(无论正不正常结束),保证信号值会被重设为semop()调用前的值。这样做的目的在于避免程序在异常情况下结束时未将锁定的资源解锁,造成该资源永远锁定。
};
五、代码实现:
Linux - 进程间通信 - 信号量的更多相关文章
- Linux进程间通信--信号量
信号量绝对不同于信号,一定要分清,关于信号,上一篇博客中已经说过,如有疑问,请移驾! 信号量 一.是什么 信号量的本质是一种数据操作锁,它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件 ...
- linux进程间通信-信号量(semaphore)
一 为什么要使用信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问 代码的临界区域.临界区域是指执 ...
- Linux进程间通信—信号量
二.信号量(semophore) 信号量是一种计数器,可以控制进程间多个线程或者多个进程对资源的同步访问,它常实现为一种锁机制.实质上,信号量是一个被保护的变量,并且只能通过初始化和两个标准的原子操作 ...
- Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()
我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,也可以屏蔽某些信号,使其不能传递给进程.那么我们应该如何设定我 ...
- Linux进程间通信(五):信号量 semget()、semop()、semctl()
这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信 -- 信号.下面 ...
- 【转载】Linux的进程间通信-信号量
原文:Linux的进程间通信-信号量 Linux的进程间通信-信号量 版权声明: 本文章内容在非商业使用前提下可无需授权任意转载.发布. 转载.发布请务必注明作者和其微博.微信公众号地址,以便读者询问 ...
- Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)
Linux进程间通信IPC学习笔记之同步二(SVR4 信号量)
- Linux进程间通信IPC学习笔记之同步二(Posix 信号量)
Linux进程间通信IPC学习笔记之同步二(Posix 信号量)
- Linux进程间通信——使用信号量
这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信——使用信号.下面 ...
随机推荐
- 定制Maven的ArcheType
根据需要定制Maven的ArcheType的好处不言而喻了,我就不再啰嗦.定制一般通过从Maven的项目构建,比手动构建省去了配置文件的编写.资源文件的复制等繁琐的操作,下面我们就说下从Maven项目 ...
- Java设计模式之《职责链模式》及应用场景
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6530089.html 职责链模式(称责任链模式)将请求的处理对象像一条长链一般组合起来,形 ...
- Rabbitmq集群高可用部署详细
序言 清风万里的季节,周末本该和亲人朋友一起消遣这烂漫的花花草草,或是懒洋洋的晒个太阳听听风声鸟鸣.无奈工作使然,理想使然,我回到啦公司,敲起啦键盘,撸起啦代码,程序狗的世界一片黯然,一片黯然,愿天下 ...
- 每天一个Linux命令 5
命令名称:touch 功能描叙:创建空文件 格式:touch 文件名 范例:$touch japan.list(当前路径创建) $touch /root/japan.list(指定路径创建) $t ...
- 1050: [HAOI2006]旅行comf
1050: [HAOI2006]旅行comf Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1495 Solved: 737[Submit][Sta ...
- 通讯录--(适配iOS7/8/9)
导入库#import <AddressBook/AddressBook.h> #import <AddressBookUI/AddressBookUI.h> #pragma m ...
- MySQL 5.6 从库开启 crash-safe 功能
原文:Enabling crash-safe slaves with MySQL 5.6 可以对从库进行配置 crash-safe 功能是 MySQL 5.6 关于复制的一个重大改进.然而,我们注意到 ...
- “玲珑杯”ACM比赛 Round #12题解&源码
我能说我比较傻么!就只能做一道签到题,没办法,我就先写下A题的题解&源码吧,日后补上剩余题的题解&源码吧! A ...
- vpn的实现原理
由于公共IP的短缺,我们在组建局域网时,通常使用保留地址作为内部IP,(比如最常用的C类保留地址:192.168.0.0-192.168.255.255)这些地址是不会被互联网分配的,因此它们在互联网 ...
- 类string解析
原创作品,转载请注明来源:http://www.cnblogs.com/shrimp-can/p/5645248.html 在涉及字符串的时候,我们可以定义字符数组或指针,其实还有一个类,专门是为字符 ...