如下图所示。
p1EanqFDPw
信号量的一般结构及PCB队列
信号量的值与相应资源的使用情况有关。
当它的值大于0时,表示当前可用资源的数量;当它的值小于0时,其绝对值表示等待使用该资源的进程个数。
注意,信号量的初值不能为负,且其值只能由P、V操作来改变。
DXDiTa9E3d
3.P、V操作的含义
P、V操作由P操作原语和V操作原语组成<原语是不可中断的过程),对信号量S进行操作,具体定义如下:
P
①将信号量S的值减1,即S=S-1;
②如果S≥0,则该进程继续执行;否则该进程状态置为阻塞状态,进程PCB排入信号量PCB队列末尾,放弃CPU,等待V操作的执行。
RTCrpUDGiT
V
①将信号量S的值加1,即S=S+1;
②如果S≤0,释放信号量队列中第一个PCB所对应的进程,将进程状态由阻塞态改为就绪态。
执行V操作的进程继续执行。
5PCzVD7HxA
一般来说,信号量S≥0时,S表示可用资源的数量。
执行一次P操作意味着请求分配一个单位资源,因此S的值减1;当S<0时,表示已经没有可用资源,请求者必须等待别的进程释放该类资源,它才能运行下去。
而执行一个V操作意味着释放一个单位资源,因此S的值加1;若S≤0,表示有某些进程正在等待该资源,因此要唤醒一个阻塞状态的进程,使之成为就绪状态。
jLBHrnAILg
4.利用信号量和P、V操作实现进程互斥
一般地,n个进程利用信号量和P、V操作实现进程互斥的一般模型如下:
进程P1进程P2……进程Pn
………………xHAQX74J0X
P
临界区;临界区;临界区;
V
……………………
其中S是互斥信号量,初值为1。
使用P、V操作实现进程互斥时应该注意的问题是:
<1)每个程序中,用户实现互斥的P、V操作必须成对出现,先做P操作,进临界区,后做V操作,出临界区。
若有多个分支,要认真检查P、V操作的成对性。
dvzfvkwMI1
<2)P、V操作应分别紧靠临界区的头尾部,临界区的代码应尽可能短,不能有死循环。
<3)互斥信号量的初值一般为1。
5.利用信号量和P、V操作实现进程同步
P、V操作是典型的进程同步机制之一。
用一个信号量与一个消息联系起来,当信号量的值为0时,表示期望的消息尚未产生;当信号量的值为非0时,表示期望的消息已经存在。
用P、V操作实现进程同步时,调用P操作测试消息是否到达,调用V操作来发送消息。
rqyn14ZNXI
使用P、V操作实现进程同步时应该注意的问题是:
<1)分析进程间的制约关系,确定信号量种类。
在保持进程间有正确的同步关系情况下,哪个进程应先执行,哪些进程后执行,彼此间通过什么信号量进行协调,从而明确要设置哪些信号量。
EmxvxOtOco
<2)信号量的初值与相应资源的数量有关,也与P、V操作在程序代码中出现的位置有关。
<3)同一信号量的P、V操作要成对出现,但它们分别在不同的进程代码中。
6.P、V操作举例
【例1】生产者-消费者问题
在多道程序环境下,进程同步是一个十分重要又令人感兴趣的问题,而生产者-消费者问题是其中一个有代表性的进程同步问题。
下面我们给出了各种情况下的生产者-消费者问题,深入地分析和透彻地理解这个例子,对于全面解决操作系统内的同步、互斥问题将有很大帮助。
SixE2yXPq5
<1)一个生产者,一个消费者,公用一个缓冲区定义两个同步信号量:
empty——表示缓冲区是否为空,初值为1。
full——表示缓冲区中是否为满,初值为0。
6ewMyirQFL
生产者进程
while(TRUE>{
生产一个产品。
P(empty>。
产品送往Buffer。
V(full>。
}
<2)一个生产者,一个消费者,公用n个环形缓冲区。
定义两个同步信号量:
empty——表示缓冲区是否为空,初值为n。
full——表示缓冲区中是否为满,初值为0。
消费者进程
while(TRUE>{
P(full>。
从bufferout=(out+1>modn;
V(empty>。
消费该产品。
}
设缓冲区的编号为1~n-1,定义两个指针in和out,分别是生产者进程和消费者进程使用的指针,指向下一个可用的缓冲区。
kavU42VRUs
生产者进程
while(TRUE>{
生产一个产品。
P(empty>。
产品送往bufferin=(in+1>modn;
V(full>。
}
<3)一组生产者,一组消费者,公用n个环形缓冲区
在这个问题中,不仅生产者与消费者之间要同步,而且各个生产者之间、各个消费者之间还必须互斥地访问缓冲区。
y6v3ALoS89
定义四个信号量:
empty——表示缓冲区是否为空,初值为n。
full——表示缓冲区中是否为满,初值为0。
mutex1——生产者之间的互斥信号量,初值为1。
mutex2——消费者之间的互斥信号量,初值为1。
设缓冲区的编号为1~n-1,定义两个指针in和out,分别是生产者进程和消费者进程使用的指针,指向下一个可用的缓冲区。
M2ub6vSTnP
生产者进程0YujCfmUCw
while(TRUE>{
生产一个产品。
P(empty>。
P(mutex1>;
产品送往bufferin=(in+1>modn;
V(mutex1>。
V(full>。
}
需要注意的是无论在生产者进程中还是在消费者进程中,两个P操作的次序不能颠倒。
应先执行同步信号量的P操作,然后再执行互斥信号量的P操作,否则可能造成进程死锁。
eUts8ZQVRd
【例2】桌上有一空盘,允许存放一只水果。
爸爸可向盘中放苹果,也可向盘中放桔子,儿子专等吃盘中的桔子,女儿专等吃盘中的苹果。
规定当盘空时一次只能放一只水果供取用,请用P、V操作实现爸爸、儿子、女儿三个并发进程的同步。
sQsAEJkW5T
分析在本题中,爸爸、儿子、女儿共用一个盘子,盘中一次只能放一个水果。
当盘子为空时,爸爸可将一个水果放入果盘中。
若放入果盘中的是桔子,则允许儿子吃,女儿必须等待;若放入果盘中的是苹果,则允许女儿吃,儿子必须等待。
本题实际上是生产者-消费者问题的一种变形。
这里,生产者放入缓冲区的产品有两类,消费者也有两类,每类消费者只消费其中固定的一类产品。
GMsIasNXkA
解:
在本题中,应设置三个信号量S、So、Sa,信号量S表示盘子是否为空,其初值为l;信号量So表示盘中是否有桔子,其初值为0;信号量Sa表示盘中是否有苹果,其初值为0。
同步描述如下:
TIrRGchYzg
intS=1。
intSa=0。
intSo=0。
main(>
{
cobegin/*表示并发操作*/
father(>。
/*父亲进程*/
son(>。
/*儿子进程*/
daughter(>。
/*女儿进程*/
coend
}
father(>/*父亲进程*/
{
while(TRUE>
{
P(S>。
/*盘子是否为空*/
将水果放入盘中。
if<放入的是桔子)
V(So>。
else
V(Sa>。
}
}
son(>/*儿子进程*/
{
while(TRUE>
{
P(So>。
/*盘中是否有桔子*/
从盘中取出桔子。
V(S>。
吃桔子。
}
}
daughter(>/*女儿进程*/
{
while(TRUE>
{
P(Sa>。
/*盘中是否有苹果*/
从盘中取出苹果。
V(S>。
吃苹果。
}
}
说明:
P、V操作有很多经典的实例,如生产者-消费者问题、读者-写者问题、哲学家就餐问题、理发店问题等,有兴趣的同学可以通过操作系统的其他教材了解一下。
7EqZcWLZNX
思考题:
四个进程A、B、C、D都要读一个共享文件F,系统允许多个进程同时读文件F。
但限制是进程A和进程C不能同时读文件F,进程B和进程D也不能同时读文件F。
为了使这四个进程并发执行时能按系统要求使用文件,现用P、V操作进行管理,请回答下面的问题:
lzq7IGf02E
<1)应定义的信号量及初值:
。
<2)在下列的程序中填上适当的P、V操作,以保证它们能正确并发工作:
A(>B(>C(>D(>
{{{{
。
[1]。
[3]。
[5]。
[7]
readF。
readF。
readF。
readF。
zvpgeqJ1hk
。
[2]。
[4]。
[6]。
[8]
}}}}
思考题解答:
<1)定义二个互斥信号量S1、S2,初值均为1,即:
S1=1,S2=1。
其中进程A和C使用信号量S1,进程B和D使用信号量S2。
NrpoJac3v1
<2)从[1]到[8]分别为:
P(S1>;V(S1>;P(S2>;V(S2>;P(S1>;V(S1>;P(S2>;V(S2>。
1nowfTG4KI
说明:
以上内容仅作为教案辅导材料,不作为考核内容。
申明:
所有资料为本人收集整理,仅限个人学习使用,勿做商业用途。