进程同步与PV操作

来源:互联网 发布:茶隼武装直升机知乎 编辑:程序博客网 时间:2024/04/29 13:00

虽然从理论上讲,每一个进程都是独立的实体,但在并发执行过程中,或因竞争资源,或者合作完成同一任务,相互之间会产生一些制约关系。一般来讲,因竞争资源产生的制约关系称为互斥关系,因合作完成同一任务而产生的制约关系称为同步关系。
例如系统中有A、B两个进程,在某一时间段,进程A正在使用打印机,而这时进程B也需要使用同一打印机,由于进程A尚未用完,那末进程B就需要等待。这样,进程B的运行受到了进程A的制约。这种制约关系就是互斥关系。
进程互斥是由共享临界资源(Critical Resource)引起的。所谓临界资源,简单来讲就是一次仅供一个进程使用的资源。事实上,系统中的许多资源都是临界资源,例如打印机、数据文件等。由于临界资源不能被多个进程同时访问,所以对临界资源的访问必须互斥地进行。因此,临界资源也称为互斥资源。进程对资源的使用是通过执行程序来实现的,进程中对临界资源进行操作的程序段称为临界区(或互斥段)。
又如函数g(x,y)=f1(x)+f2(y)由进程A、B合作计算,进程A计算g1=f1(x);进程B计算f2(y),并在最后求出g(x,y)的值。可以看出,在计算f1(x)和f2(y)时,进程A和进程B各自独立(即并发)地执行,但是在进程B计算g1+f2(y)时受到进程A的制约,即进程A必须完成g1=f1(x)的 计算。进程A、B间的这种制约关系就是同步关系。
上面的例子说明,系统中并发执行着的进程往往需要互斥或同步。那么怎样才能使进程根据需要自动进行互斥或同步呢?为实现进程互斥和同步,操作系统中采用了许多方法,比如用添加程序段实现进程互斥和同步的所谓软件法、用加锁原语和解锁原语实现的锁操作法,还有信号量与P、V操作以及管程等。其中信号量与P、V操作由于效果好而成为现代操作系统中实现进程互斥和同步的基本常用方法。所以,我们仅介绍信号量与P、V操作及其相关的进程同步方法。
(1) 信号量与P、V操作
信号量是一种整型变量,通常用S表示。信号量S的物理意义是:若S≥0,则S的值表示系统中与S联系着的某类可用资源的个数;若S<0,则S的绝对值表示S的阻塞队列中进程的个数。P、V操作实际是关于信号量S的两个原语,其定义如下:
P(S): ① S=S-1;
② 若S≥0,则调用P(S)的进程继续运行;
③ 若S<0,则调用P(S)的进程被阻塞,并把它插入到等待信号量S的阻塞队列中。
V(S): ① S=S+1;
② 若S>0,则调用V(S)的进程继续运行;
③ 若S≤0,从等待信号量S的阻塞队列中唤醒头一个进程,然后调用V(S)的进程继续运行。

⑵ 利用信号量和P、V操作实现进程互斥
设进程P1、P2需互斥地使用某一临界资源R,为此设置一个公用信号量S,并置初值S=1,表明该临界资源未被占用;然后给进程P1和P2的临界区两端分别添加P、V操作P(S)和V(S),即可实现两进程的互斥。程序段如下:
P1:                             P2:
P(S)                          P(S)
critical section        critical section
V(S)                           V(S)
由于信号量的初值为1,故第一个进程P1执行P操作后信号量S的值减为0,表明临界 资源空闲,可分配给该进程,使之进入临界区。若此时又有第二个进程P2欲进入临界区,也应先执行P操作,结果使S=-1,表示临界资源已被占用,因此第二进程变为阻塞状态。当第一个进程在临界区内将程序执行完毕,然后执行V操作,释放该资源而使信号量S的值恢复到0,又唤醒了第二个进程P2。待第二个进程P2完成对临界资源的使用后,又执行V操作,最后使信号量S恢复到初值1。

例1 设一民航售票系统有n个售票处。每个售票处通过终端访问系统中的公用数据区,假定公共数据区中的一些单元Xk(k=1,2,...)分别存放×月×日×次航班的现存票数。设P1,P2,…,Pn表示各售票处的处理进程,R1,R2,…,Rn表示各进程执行时所用的工作单元。用信号量实现进程间互斥的程序如下:
begin
S=1
cobegin
Process Pi(i=1,2,......,n)
begin
按旅客订票要求找到Xk;
P(S)
Ri=Xk;
If Ri>=1 then begin
Ri=Ri-1;
Xk=Ri;
V(S)
输出一张票
end
else begin
V(S);
输出“票已售完”
end
end
coend
end

⑶ 利用信号量和P、V操作实现进程同步
下面通过一个实例来说明利用信号量和P、V操作实现进程同步的方法。
例2 设进程A、B是两个相互合作的进程,共用一个缓冲区。进程A负责从卡片输入机读入卡片送到缓冲区,进程B取走缓冲区中的卡片信息,并进行加工处理。进程A在完成将卡片送入缓冲区后,给进程B发一信号。进程B收到信号后,从缓冲区取走卡片信息,然后给进程A发一信号。这一过程重复进行。这也是一个进程同步问题。为此,可利用两个私用信号量S1和S2。S1初值为1,S2初值为0,信号量S1表示缓冲区是否有卡片信息,S2表示缓冲区信息是否被取走。利用P、V操作实现进程A、B的同步算法如下:

生产者(进程) 消费者(进程)
┌─────┐ ┌─────┐
↓                    │ ↓ │
生产一个产品│ P(S0) │
P(Sn)             │ P(S) │
P(S)               │ 从缓冲池取出一个产品│
向缓冲池放入一个产品│ V(S) │
V(S)               │ V(Sn) │
V(S0)            │ 消耗该产品 │
↓                   │ ↓ │
└─────┘ └─────┘ 

 
现在可对上述同步算法作一简单解释。假定进程A开始执行,它启动读卡机工作,执行P(S1),使得S1的值由1变为0;由于S1=0,进程A继续运行,将卡片信息送入缓冲区;然后执行V(S2),使S2=1,表示缓冲区已装入卡片信息。这时,如果进程A再执行P(S1),则S1变为-1,于是进程A进入阻塞队列。调度程序调度进程B执行,进程B执行P(S2),使S2=0,进程B继续运行,将缓冲区信息取出,再执行V(S1),使S1=1,则唤醒进程A,使其变为就绪,然后进程B继续执行,如果返回到执行P(S2),使S2=-1,则进程B进入阻塞队列,停止执行。调度程序将在下一次把处理机分配给进程A时,进程A和进程B又重复上述过程,如此循环,直至读卡机上的全部卡片读完为止。
类似地,也可以用信号量和P、V操作实现计算进程和打印进程之间的同步。每当计算进程将所得结果送入缓冲区,由打印进程将该结果从缓冲区取走,进行打印输出。