怎么突然没信号了?
这篇推送,我们第一次尝试做“标题党”,来说说操作系统进程间通信的另外两种重要方式——信号和信号量。
(一) 信号
对于信号这个东西,我想在平时生活中可以遇到各种各样的事物体现。比如:交通信号灯,路牌,或者某个暗恋的异性给出的信号。最早使用信号的例子可以追溯到春秋战国时期的烽火台。因此,我们可以非常容易地去理解信号实际的含义,就是双方事先约定好某一个协议,比如,狼烟起来时就代表有敌军进攻,因此一旦某个烽火台上的狼烟起来了,下一个烽火台在视距范围内就可以看到这个狼烟,进而解析出其含义就是“敌军进攻了”,仅此而已,非常简单。
操作系统进程间的通讯,也是一样的道理,比如某个任务检测到了某一件事情,然后通过API将特定的信号加入到信号集里面,比如Linux使用的是函数:“int sigaddset(sigset_t *set, int signo);”。监视此信号的任务,只需要在被执行时查询信号集,此信号是否被加入了信号集,即可完成相应的操作,比如Linux使用API “int sigismember(const sigset_t *set, int signo);”来查询。说到这里,关于信号的整体操作方式就是如此,非常简单。当然实际使用的过程中,还牵涉到进程的信号屏蔽码,信号屏蔽码可以用来在某段时间内阻塞一些信号集中的信 号,如果信号不在信号集中,就不必讨论它,因为肯定不响应,是否能生成也不肯定,我没有做过试验。综上所述,信号其实就是类似于我们平时使用的标志位。
(二) 信号量
”信号量“虽然和”信号“只相差一个字,但是它们的区别就像黑色和白色一样巨大。他们虽然都可用来实现同步和互斥,但信号是使用信号处理器来进的,信号量是使用P,V作来实现的。所谓P,V其实是一对互斥的操作,我们可以将其称为”PV原语“。信号量的概念1965年由著名的荷兰计算机科学家Dijkstra提出,其基本思路是用一种新的变量类型(semaphore)来记录当前可用资源的数量。有两种实现方式:1)semaphore的取值必须大于或等于0。0表示当前已没有空闲资源,而正数表示当前空闲资源的数量;2) semaphore的取值可正可负,负数的绝对值表示正在等待进入临界区的进程个数。
P原语:P是荷兰语Proberen(测试)的首字母。为阻塞原语,负责把当前进程由运行状态转换为阻塞状态,直到另外一个进程唤醒它。操作为:申请一个空闲资源(把信号量减1),若成功,则退出;若失败,则该进程被阻塞;
V原语:V是荷兰语Verhogen(增加)的首字母。为唤醒原语,负责把一个被阻塞的进程唤醒,它有一个参数表,存放着等待被唤醒的进程信息。操作为:释放一个被占用的资源(把信号量加1),如果发现有被阻塞的进程,则选择一个唤醒之。
===============华丽的分割线,以下是乐创客的解释=================
首先,我们先概括一下,P操作,实际上是一个”拿“的操作,V操作,实际上是一个”给“的操作,而一般来说,系统初始化时,某一个硬件允许的最大访问量是一个固定的常数,就以串口来说,同一时间只允许一个进程去访问,因此它的常数就为1,也就是说,只有当P操作成功时,也就是你成功拿走了这个1时,系统才会允许进程对此资源进行访问,而此时的常数就被设置成0了。等到下一个任务再来用P操作申请访问串口时,这个常数就会被设置成-1,那么系统就会让此任务进入阻塞状态(简单理解成等待)。也就是说,如果这个常数为-n(n>=0),那么就代表有n个任务在阻塞中,等待访问此资源。而一旦拥有次资源的任务使用完成后,并且用V操作释放后,那么这个常数就会加1,最先排队(或者优先级较高的任务,具体看调度算法)的任务将会跳出阻塞状态,进而获取该资源。
P操作
V操作
其实,PV操作就像你去使用信用卡,你的额度一定,每次刷卡,P的一声,刷到你的额度刷爆之后,就不能刷了,直到把额度还进去,才可以继续刷。哈哈,这是小编举过的最恰当的例子,连”VISA“的第一个字母和V操作都那么的毫无违和感。