信号量的本质是种数据操作锁,它本不具有数据交换的功能,是通过控制其他的通信资源(件,外部设备)来实现进程间通信它本只是种外部资源的标识。信号量在此过程中负责数据操作的互斥、同步等功能。

当请求个使信号量来表的资源时,进程需要先读取信号量的值来判断资源是否可0,资源可以请求,等于0,资源可,进程会进睡眠状态直资源可。 当进程不再使个信号量控制的共享资源时,信号量的值+1,对信号量的值进的增减 操作均为原操作,这是由于信号量主要的作是维护资源的互斥或多进程的同步访问。 在信号量的创建及初始化上,不能保证操作均为原性。

一、为什么要使信号量
为了防出现因多个程序同时访问个共享资源引发的系列问题,我们需要种法, 它可以通过成并使令牌来授权,在任时刻只能有个执线程访问代码的临界区域。 临界区域是指执数据更新的代码需要独占式地执。信号量就可以提供这样的种访 问机制,让个临界区同时间只有个线程在访问它, 也就是说信号量是来调协进程 对共享资源的访问的。其中共享内存的使就要到信号量。

二、信号量的作原理

由于信号量只能进两种操作等待和发送信号,即P(sv)和V(sv),他们的为是这样的:
P(sv):如果sv的值于零,就给它减1;如果它的值为零,就挂起该进程的执
V(sv):如果有其他进程因等待sv被挂起,就让它恢复运,如果没有进程因等待sv挂 起,就给它加1. 举个例,就是两个进程共享信号量sv,旦其中个进程执了P(sv)操作,它将得到信号 量,并可以进临界区,使sv1。第个进程将被阻进临界区,因为当它试图执
P(sv)时, sv0,它会被挂起以等待第个进程离开临界区域并执V(sv)释放信号量,这时 第个进程就可以恢复执。

Linux的信号量机制
Linux提供了组精设计的信号量接来对信号进操作,它们不只是针对进制信号量,下将会对这些函数进介绍,但请注意,这些函数都是来对成组的信号量值进 操作的。它们声明在头件sys/sem.h中。 【信号量的意图在于进程间同步,互斥锁和条件变量的意图则在于线程间同步。但是信号 量也可于线程间,互斥锁和条件变量也可于进程间。我们应该使适合具体应的那组原语。】

描述
semctl() semid 标识的信号量集上,或者该集合的第 semnum 个信号量上执 cmd 指定的 控制命令。 (信号量集合索引起始于零。)根据 cmd 不同,这个函数有三个或四个参数。当有四个参数时,第四个参数的类型是 union 。调程序必须按照下式定义这个联合体:
union semun {
int val; // 使的值
struct semid_ds *buf; // IPC_STATIPC_SET 使缓存区
unsigned short *array; // GETALL,SETALL使用的数组

Struct seminfo *__buf;//IPC_INFO(linux特有)使用缓存区

};

注意:该联合体没有定义在任何系统头文件中,因此得用户自己声明。<Centos下确实是这样,但是UNIX下不同,不需要自己定义声明>

代码实现如下:

//sem.h

wKioL1dojADCBFRcAACoUnRPdKo541.png


//sem.c

wKioL1dojB6ymWipAACZWeySXb8778.png

wKiom1dojDCTRegxAACFcq6bFF8500.png

//test.c

wKioL1dojFLx4b0nAABnpRQg5Yk229.png

运行结果如下:

wKioL1dojLOzmiToAAAZ-IGnCkU096.png-wh_50

总结:

信号量的p和v操作都是原子操作,在执行操作时,两个进程共享一个信号量,两个进程之间存在互斥关系。