目录
1.进程的互斥
进程互斥是进程同步控制中的一种特例。
1.1临界资源和临界区
临界资源
:某段时间内只允许一个进程使用的资源。
临界区
:使用临街资源的那一部分程序。
1.2遵循准则
为了提供对互斥的支持,系统必须满足以下条件:
(1)空闲让进:某进程退出临界区,刚好有其他进程等待进入临界区,那么就让它进入。
(2)忙则等待:有进程在临界区中,其他进程必须进行等待。
(3)有限等待:不能让一个进程在临界区中无限运行,在有限时间内让它退出。
(4)让权等待:如果有优先级更高的进程在等待区中,那么就让临界区的进程让位。
1.3使用硬件实现互斥
中断禁用
:保证进程进入临界区后不被打断,有效的实现互斥。
while(true)
{
/*禁用中断*/
临界区
/*启用中断*/
}
缺点:
(1)代价太高,会降低执行效率
(2)不能用于多核处理器结构
专用机器指令
:compare_and_swap 指令
优点:
(1)适用范围广
(2)使用简单
(3)可支持多个临界区
缺点:
(1)导致CPU空耗,当一个进程等待进入临界区时,会不断地持续检测
(2)导致饥饿进程,都有多个进程都等待进入临界区是,在某些极端情况下可能会导致某个进程永远无法进入临界区。
1.4信号量实现互斥
信号量是一个数据结构,简写为s。主要有两个原语操作wait和signal。
原语wait(s)
:用于申请一个资源,有时候写为P
void wait(semaphore s)
{
//申请时,资源数减一,如果此时资源数小于0,说明无空闲资源,那么将进程阻塞,并将其放入等待队列
s.value=s.value-1;
if(s.value<0)
block(s.queue);
}
原语signal(s)
:用于释放一个资源,有时候写为V
void signal(semaphore s)
{
//将资源数加一,如果此时资源数小于等于0,那么将进程唤醒,并将其放入就绪队列
s.value=s.value+1;
if(s.value<=0)
wakeup(s.queue);
}
信号量的物理含义
:在使用时对信号量进行初始化,注意初始值应该大于等于0。
在使用wait和signal原语时需要注意使用顺序,否则可能会出现死锁。
2.进程的同步
在使用信号量实现进程同步时,一个信号量需要和一个消息对应起来。
2.1生产者\消费者问题
问题描述
:生产者生产产品放入缓冲区中,当缓冲区满时则发生阻塞。消费者从缓冲区中取出产品,当缓冲区为空时,则发生阻塞。
解决方案
:这里我们设置三个信号量,S1、mutex、S2,分别表示缓冲区是否还有空位、该时刻只可以进行一个操作(生产或者消费)、缓冲区是否已满;定义两个变量i和j分别指向生产产品的位置和消费产品的位置。
2.2读者\写者问题
问题描述
:读者和写者共享一组数据区,允许多个读者同时执行读操作,不允许读者、写者同时操作,不允许多个写者同时操做。
解决方案
:假设读优先,即有写着等待,但是有其他读者读,那么新读者也可以进行读操作。设置信号量w用于读者和写者、写者和写者之间的互斥;设置信号量readcount表示正在读的读者个数;设置mutex来对readcount这个临界资源的互斥访问。
3.进程之间的通信
进程之间根据通信内容可以分为控制信息的传送
和大批量数据的传送
;根据高级通信机制可以分为:共享内存方式
、管道通信机制
、消息传递机制
。
3.1共享内存方式
使用共享内存可以避免对一个内容的反复访问,但是要注意实现存储区访问的互斥。
3.2管道通信机制
管道通信用于连接一个读进程和一个写进程,实现进程之间通信的一种共享文件,又称为pipe文件。
以字符流形式将大量数据送入管道,它可以传送大量数据,因此被广泛采用。
3.3消息传递机制
以信息为单位,可以分为直接通信方式和间接通信方式。
直接通信方式
:发送进程直接将消息发给接受进程,接受进程可以接受任意发送发的消息,并且知道发送方是谁。
简介通信方式
:消息并不直接送达,而是发送到临时消息队列(信箱)。具有很大的灵活性,可以一对一、一对多、多对多、多对一。
4.管程
把分散在各进程中的临界区集中起来进行管理,防止进程有意或者无意的违法同步操作。