进程间通常需要相互通信,那么进程间是如何进行信息传递的呢?怎么确保多个进程在关键活动中不会出现交叉?怎样保证进行活动是按照想要的顺序执行的呢?
相关概念:
- 竞争条件:两个或多个进程读写某些共享数据,而最后的结果取决于进程运行的精确时序。
- 临界区:对共享内存(数据)进行访问的程序片段。
- 优先级翻转:针对不同优先级的进程访问同意临界区,由于调度规则限定只要高优先级处于就绪状态就可以运行,若某一时间低优先级进程先行进入临界区,且尚未离开,此时高优先级处于就绪状态,由于低优先级不会再次被调度,高优先级进程将一直处于等待状态。
1 互斥方案
互斥方案用于保证当一个进程在临界区操作时,其他进程不会进入临界区。
1.1 屏蔽中断
屏蔽中断即每个进程一进入临界区立即屏蔽所有中断,然后在离开前再打开中断。
缺点:
- 将屏蔽中断的权利交予用户进程,不可控因素太多,若进程屏蔽后未及时打开,可能导致系统崩溃;
- 对于多处理器,仅对当前运行CPU有效;
1.2 锁变量
锁变量法是一种软件解决方案,其思想为设置一个共享锁变量,为其设置初始值(假设为0),当一个进程进入临界区,它将首先检测锁变量的值是否为0,若是,则将锁变量的值设置为加锁值(假设为1);若非0,则进行等待。
缺点:该方法不能彻底解决互斥问题,若进程A读取锁变量值为0,且未解锁,此时CPU调度进程B,此时进程B读取锁变量也将为0。
1.3 严格轮换法
严格轮换法的思想是要求两个进程严格第轮流进入他们的临界区。如下图所示:
1.4 Peterson解法
Peterson算法示例:
1 | #define FALSE 0 |
1.5 TSL指令
通过硬件加锁的方式,使用命令TSL RX,LOCK
将一个内存字lock读到寄存器RX中,然后在该内存地址上存一个非零值。执行该指令的CPU将锁住内存总线,以禁止其他CPU在本指令结束之前访问内存。
锁住存储总线和屏蔽中断有什么区别?
屏蔽中断:对于多处理器无效,仅会屏蔽当前处理CPU。
锁住总线:通过一个特殊的硬件设备,保证其他处理器也无法使用。
2 信号量
信号量使用一个整型变量来累计唤醒次数,其取值可以为0(标识没有被保存下来的唤醒操作)或正值(标识有一个或多个唤醒操作)。
信号量有两种操作:
- down(sleep)-P操作:
- 信号量的值大于0:将值减1并继续;
- 信号量的值等于0:将进程将睡眠,此时down操作并未结束。
- up(wakeup)- V操作:对信号量的值增加1。有一个或多个进程在该信号量上睡眠,无法完成先前的down操作,则由系统选择一个,并允许该进程完成它的down操作。