操作系统PV操作及读者写者问题
目录:
1、信号量:
2、P、V操作原语可描述为以下式子:
3、解释:
4、互斥模式原理:
5、同步模式原理:
6、读者写者问题:
1、信号量:
PV操作与信号量的处理有关,信号量是表示资源的实体,是一个与队列有关的整型变量,其值只能由P、V操作来改变。操作系统利用信号量对进程和资源进行控制和管理。
2、P、V操作原语可描述为以下式子:
procedure P(var s:samephore);
{
s.value=s.value-1;
if (s.value<0)
asleep(s.queue);
}
procedure V(var s:samephore);
{
s.value=s.value+1;
if (s.value<=0)
wakeup(s.queue);
}
其中用到两个标准过程:
asleep(s.queue):执行此操作的进程的PCB进入s.queue尾部,进程变成等待状态
wakeup(s.queue):将s.queue头进程唤醒插入就绪队列
s.value初值为1时,可以用来实现进程的互斥。
3、解释:
P(S):
(1)S:=S-1;
(2)若S>=0,则调用P(S)的进程继续运行。
(3)若S<0,则调用P(S)的进程被阻塞,并把它插入到等待信号量S的阻塞队列中
V(S):
(1)S:=S+1;
(2)若S>0,则调用V(S)的进程继续运行;
(3)若S<=0,从等待信号量S的阻塞队列中唤醒头一个进程,然后调用V(S)的进程继续运行
4、互斥模式原理:
S:=1
进程P1 进程P2
P(S) P(S)
S1 S2
V(S) V(S)
分析:由于信号量的初值为1,故第一个进程P1执行P操作后信号量减为0,表明临界资源空闲,可分配给该进程,使之进入临界区。若此时又有第二个进程P2欲进入临界区,也应先执行P操作。结果使S=-1,表示临界资源已被占用,因此第二进程变为阻塞状态,当第一个进程在临界区内将S1执行完后再执行V操作,释放该资源而使信号量恢复到0,有唤醒了第二个进程P2。待第二个进程P2完成对临界资源的使用(S2)后,又执行V操作,最后信号量恢复到初值1。
5、同步模式原理:
S:=0
进程P1 进程P2
L1:P(S) L2:V(S)
分析:设进程P1先到达L1点,当它执行P(S)时,使S=-1;
于是P1进入阻塞状态并进入信号量S的阻塞队列;
然后进程P2到达L2点,当它执行到V(S)时,将S值变为0,于是唤醒P1,使其转变为就绪状态,当再次调度到进程P1时,则P1可在L1点后继续运行下去,由此可见,当进程P1到达L1时,除非进程P2已过了L2点,否则进程P1就要暂停执行,这就是说,P1在L1点必须与进程P2进行同步。在这种同步操作中,进出那个P1受到进程P2的制约,而进程P2却不受进程P1的制约,所以是非对称的。
6、读者写者问题:
(1)满足条件:①写写互斥;②读写互斥;③读读同时
(2)单纯使用信号量不能解决读者与写者问题,必须引入计数器readcount对读进程计数;rmutex是用于对计数器readcount操作的互斥信号量;wmutex表示是否允许写的信号量;
(3)代码示例:
semaphore rmutex = 1, wmutex = 1; //rmutex 是用于对计数器readcount操作的互斥信号量;wmutex表示是否允许写的信号量;
int readcount = 0; //整型变量,表示读者数
void reader(){
do{
P(rmutex); //开始对rc共享变量进行互斥访问
if(readercount == 0) //如是第一个读者进行读进程,判断是否有写进程在临界区,若有,读进程等待,若无,阻塞写进程
P(wmutex);
readercount++;//来了一个读进程,读进程数加1
V(rmutex); //结束对readcount共享变量的互斥访问
……
perform read operation;//读操作
……
P(rmutex); //开始对rc共享变量的互斥访问
readcount--; //一个读进程读完,读进程数减1
if(readcount==0) //最后一个离开临界区的读进程需要判断是否有写进程需要进入临界区,若有,唤醒一个写进程进临界区
V(wmutex);
V(rmutex);//结束对rc共享变量的互斥访问
}while(TRUE);
}
void writer(){
do{
P(wmutex);//无读进程,进入写进程;若有读进程,写进程等待
perform write operation;//写操作
V(wmutex); //写进程完成;判断是否有读进程需要进入临界区,若有,唤醒一个读进程进临界区
}while(TRUE);
}
void main(){
cobegin
reader(); writer();
coend
}