AT&T的贝尔实验室,对Unix早期的进程间通信进行了改进和扩充,形成了"system V IPC",其通信进程主要局限在单个计算机内。IPC对象指的是共享内存(share memory)、消息队列(message queue)和信号灯集(semaphore)。
信号灯(semaphore),也叫信号量。
本质;一种数据操作锁(本身是一个计数器,是对临界资源的保护),它本身不具有数据交换的功能,而是通过控制其他的通信资源(文件,外部设备)来实现进程间通信,它本身只是一种外部资源的标识。信号量在此过程中负责数据操作的互斥、同步等功能。
当请求一个使用信号量来表示的资源时,进程需要先读取信号量的值来判断资源是否可用。大于0,资源可以请求,等于0,无资源可用,进程会进入睡眠状态直至资源可用。当一个进程不再使用一个信号量控制的共享资源时,信号量的值+1,对信号量的值进行的增减操作为原子操作,这是由于信号量主要的作用是维护资源的互斥或多进程的同步访问。而信号量的创建以及初始化上,不能保证操作为原子操作。
使用信号量的原因:为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,它可以通过生成并使用令牌来授权,在任意时刻只能有一个执行线程访问代码的临界区域。临界区域是指执行数据更新的代码需要独占式地执行。而信号量就可以提供这样的一种访问机制,让一个临界区同一时间只有一个线程在访问它,也就是说信号量是用来协调进程对共享资源的访问的。
缺点:创建和初始化分离。
信号灯是不同进程间或一个给定进程内部不同线程间同步的机制。System V的信号灯是一个或者多个信号灯的一个集合。其中的每一个都是单独的计数信号灯。System V 信号灯由内核维护。主要函数semget,semop,semctl。
1、semget函数:创建一个信号量集对象(得到一个信号量集标识符)
函数原型:int semget(key_t key,int nsems,int semflg)
key:由ftok()函数的得到
nsems:创建信号量集中信号的个数
semflg:
IPC_CREAT:若内核中不存在键值与key相等的信号量集,则创建,否则,返回此信号量集的标识符
IPC_EXCL:单独使用无意义
IPC_CREAT | IPC_EXCL :创建一个新的信号量集并返回信号量集的标识符,否则,返回-1.
返回值:成功返回信号量集的标识符。失败返回-1.
2、semctl函数:在指定的信号集或信号集内的某个信号上执行操作控制
函数原型:int semctl(int semid,int semnum,int cmd,union semun arg)
semid: 信号量集标识符
semnum:信号量集数组上的下标,表示某一个信号量
arg:
union semun {
short val; /*SETVAL用的值*/
struct semid_ds* buf; /*IPC_STAT、IPC_SET用的semid_ds结构*/
unsigned short* array; /*SETALL、GETALL用的数组值*/
struct seminfo *buf; /*为控制IPC_INFO提供的缓存*/
} arg;
3、semop函数:对信号量进行P,V操作(本文的重点)
P操作负责把当前进程由运行状态转换为阻塞状态,直到另外一个进程唤醒它。操作为:申请一个空闲资源(把信号量减1),若成功,则退出;若失败,则该进程被阻塞;
V操作负责把一个被阻塞的进程唤醒,它有一个参数表,存放着等待被唤醒的进程信息。操作为:释放一个被占用的资源(把信号量加1),如果发现有被阻塞的进程,则选择一个唤醒之。
semop函数原型如下:
int semop(int semid, struct sembuf *sops, unsigned nsops);
semop操作中:sembuf结构的sem_flg成员可以为0、IPC_NOWAIT、SEM_UNDO 。为SEM_UNDO时,它将使操作系统跟踪当前进程对这个信号量的修改情况,如果这个进程在没有释放该信号量的情况下终止,操作系统将自动释放该进程持有的。
sembuf结构的sem_flg成员为SEM_UNDO时,它将使操作系统跟踪当前进程对这个信号量的修改情况,如果这个进程在没有释放该信号量的情况下终止,操作系统将自动释放该进程持有的信号量,从而使另外一个进程可以继续工作,防止其他进程因为得不到信号量而发生【死锁现象】。为此一般建议使用SEM_UNDO。
测试代码:
sem.h
650) this.width=650;" src="http://s5.51cto.com/wyfs02/M01/84/8A/wKioL1eTcqSxR0NoAAB3ZBA4OxA801.png-wh_500x0-wm_3-wmp_4-s_1894491761.png" title="1.png" width="300" height="275" border="0" hspace="0" vspace="0" style="width:300px;height:275px;" alt="wKioL1eTcqSxR0NoAAB3ZBA4OxA801.png-wh_50" />
sem.c
650) this.width=650;" src="http://s2.51cto.com/wyfs02/M01/84/8A/wKioL1eTcyrhkLR7AABogO2O3hk363.png-wh_500x0-wm_3-wmp_4-s_338026762.png" style="width:300px;height:286px;" title="2.png" width="300" height="286" border="0" hspace="0" vspace="0" alt="wKioL1eTcyrhkLR7AABogO2O3hk363.png-wh_50" />
650) this.width=650;" src="http://s2.51cto.com/wyfs02/M02/84/8A/wKiom1eTcyqD4Lw0AABe270bJ6U000.png-wh_500x0-wm_3-wmp_4-s_115928713.png" style="width:300px;height:283px;" title="3.png" width="300" height="283" border="0" hspace="0" vspace="0" alt="wKiom1eTcyqD4Lw0AABe270bJ6U000.png-wh_50" />
650) this.width=650;" src="http://s4.51cto.com/wyfs02/M02/84/8A/wKiom1eTcyvAlnf-AABgNhHVxWs835.png-wh_500x0-wm_3-wmp_4-s_3766153782.png" style="width:300px;height:254px;" title="4.png" width="300" height="254" border="0" hspace="0" vspace="0" alt="wKiom1eTcyvAlnf-AABgNhHVxWs835.png-wh_50" />
semtest.c
650) this.width=650;" src="http://s4.51cto.com/wyfs02/M00/84/8A/wKioL1eTcyvgMbXHAABT8YfEGhE369.png-wh_500x0-wm_3-wmp_4-s_2876800967.png" style="width:300px;height:254px;" title="5.png" width="300" height="254" border="0" hspace="0" vspace="0" alt="wKioL1eTcyvgMbXHAABT8YfEGhE369.png-wh_50" />
650) this.width=650;" src="http://s5.51cto.com/wyfs02/M00/84/8A/wKiom1eTcyyhOCOkAAA9nTYAIKw397.png-wh_500x0-wm_3-wmp_4-s_1601240996.png" style="width:300px;height:192px;" title="6.png" width="300" height="192" border="0" hspace="0" vspace="0" alt="wKiom1eTcyyhOCOkAAA9nTYAIKw397.png-wh_50" />
运行结果:
650) this.width=650;" src="http://s5.51cto.com/wyfs02/M01/84/8A/wKioL1eTcyyyYC_1AAA2v98qPkI917.png-wh_500x0-wm_3-wmp_4-s_4010290961.png" style="width:300px;height:180px;" title="7.png" width="300" height="180" border="0" hspace="0" vspace="0" alt="wKioL1eTcyyyYC_1AAA2v98qPkI917.png-wh_50" />
本文出自 “缘去即成幻” 博客,请务必保留此出处http://liu153.blog.51cto.com/10820414/1829429