优秀课件笔记之进程管理(下)

1、本文所以内容来自 著名高校课件和学生笔记(校园里面经常见到有人高价买笔记)
2、任课教师不会提供参考文献,所以只能对作者表示感谢,如果引用了您的作品,可以用回复方式补充参考文献。
3、我不对文章无关问题进行解答,文章内容也比较难,我也很难解答您遇到的问题,如果发现BUG可以用回复方式帮我修正。
4、本课 计算机操作系统
,适用于计算机操作系统课、考研

本课其他部分的导航条见页面底部
§3.7  进程通信
§3.8  死锁问题
§3.9  线程
本章小结

 

3.7.3
邮箱通信
邮箱通信就是由发送进程申请建立一与接收进程链接的邮箱。发送进程
把消息送往邮箱,接收进程从邮箱中取出消息,从而完成进程间信息交
换。设置邮箱的最大好处就是发送进程和接收进程之间没有处理时间上
的限制。一个邮箱可考虑成发送进程与接收进程之间的大小固定的私有
数据结构,它不像缓冲区那样被系统内所有进程共享。邮箱由邮箱头和
邮箱体组成。其中邮箱头描述邮箱名称、邮箱大小、邮箱方向以及拥有
该邮箱的进程名等。邮箱体主要用来存放消息(图3.17
)。
图3.17
邮箱通信结构
101
对于只有一发送进程和一接收进程使用的邮箱,则进程间通信应满
足如下条件:

发送进程发送消息时,邮箱中至少要有一个空格能存放该消息。

接收进程接收消息时,邮箱中至少要有一个消息存在。
设发送进程调用过程
deposit(m)
将消息发送到邮箱,接收进程调用过程
remove(m)
将消息m
从邮箱中取出。另外,为了记录邮箱中空格个数和
消息个数,信号量fromnum
为发送进程的私用信号量,信号量mesnum
为接收进程的私用信号量。fromnum
的初值为信箱的空格数
n

mesnum
的初值为
0
。则
deposit(m)
和remove(m)
可描述如下:
deposit(m
):
remove(m
):
begin local x begin local x
P(fromnum

P(mesnum

选择空格x
选择满格x
将消息m
放入空格x

把满格x
中的消息取出放m

置格x
的标志为满
置格x
标志为空
V(mesnum

V(fromnum

end
end
Ø 显然,调用过程deposit(m
)
的进程与调用过程remove(m
)
的进程之间存
在着同步制约关系而不是互斥制约关系。
Ø 另外,在许多时侯,存在着多个发送进程和多个接收进程共享邮箱的情
况。这时需要对过程deposit(m
)
和remove(m
)
作相应的改动。?
102
3.7.4
进程通信的实例——
和控制台的通信
通用计算机中,除了用户终端之外,还有一台由系统操作
员控制的控制台终端。各用户进程可将消息送到控制台进
程,操作员在读到这些消息后做出相应的处理。
设控制台终端由键盘和显示器组成,终端和主机之间按全
双工模式发送和接收数据,即键盘和数据显示彼此独立。
设键盘控制进程和显示控制进程分别为KCP
和DCP
,用户
进程和控制台终端的通信由会话控制进程CCP
控制完成。
其中控制台键盘的输入放入缓冲队列inbuf
中,CCP
可从
inbuf
中取出消息从而得到来自控制台的指示。而CCP
所提
出的问题则以消息形式放入控制台的输出缓冲队列outbuf
中,DCP
从outbuf
中取出消息送至显示器,以供操作员判
断。其通信过程如图3.18

103
图3.18
和控制台通信示例
104
下面,先描述KCP
与键盘、DCP
与显示器之间的通信
动作;然后描述CCP
与KCP
及DCP
的接口;紧接着再给出
CCP
与用户进程的接口;最后再综合描述CCP
的动作。
(1) KCP
和DCP
的动作
Ø 以上通信过程是一个严格的提问/
回答方式的通信例子。先描述KCP

DCP
的动作(下面描述中省略了进程的PCB
部分)。
Ø 首先,当操作员打键时,KCP
将对应的数据从键盘送入输入缓冲inbuf
中,同时,也将键入数据送echobuf
在显示器上显示。显然,KCP

CCP
等之间的通信满足消息机制的条件。另外,除了KCP
和CCP
的通
信之外,KCP
实际上还在和键盘发生通信。因此,在描述KCP
和CCP
时,还必须考虑KCP
和键盘的通信。
105
uKCP
可描述如下:
键盘控制进程KCP:
设T-Ready
和T-Busy
分别为键盘KP
和键盘控制进程
KCP
的私用信号量,其初值为0
和1

初始化{清除所有inbuf
和echobuf
}
begin local x
P(T-Ready

从键盘数据传输缓冲x
中取出字符m
记为x.m
Send(x.m)
将x.m
送入echobuf
V(T-Busy

end
Ø 这里,假设了键盘也可用进程描述为:
键盘动作KP

repeat local x
P(T-Busy

把键入字符放入数据传输缓冲x
V(T-Ready

Until
终端关闭
106
同样,可以写出DCP
和显示器动作DP
的通信动作:
l 显示器控制进程DCP

设D-Ready
和D-Busy
分别为DP
和DCP
的私用信号量且初值为0
和1

初始化
{
清除输出缓冲outbuf
,echo
模式置false}
begin
if
outbuf

then
receive(k
) /
*
CCP k
*
/

(D-Busy

把k
送入显示器数据缓冲区
V(D-Ready

else
echo
模式置true
echobuf
中字符置入显示器数据缓冲区
fi
107
l 显示器动作DP

repeat
if
echo
模式
then
打印显示器数据缓冲区中字符
else
P(D-Ready

打印显示器数据缓冲区中消息
V(D-Busy
yuBDs

Until
显示器关机
Ø 这里,假定了一个消息的长度总是小于outbuf
的长度。
108
(2) CCP
和KCP
及DCP
的接口
上面已经描述了KCP
与KP
,DCP
与DP
的同步动作部分。那么,KCP
,DCP

CCP
之间又是如何动作的呢?现在来看CCP
怎样从inbuf
中读出消息和怎样把
消息写入outbuf
。这里,仍然假定1
个消息的长度小于outbuf
和inbuf
的长度。
设过程Read(x)
把inbuf
中的所有字符读到用户进程数据区x
处,过程Write(y)

用户进程y
处的消息写到outbuf
中。则Read(x)
和Write(y)
可分别描述如下:
Read(x
):
Write(y
teyWr
):
Begin
begin
P
(inbuf
-full


(outbuf
-empty

Copy(inbuf
into x)
Copy(outbuf
from y)

(inbuf
-empty

V(outbuf
-full

end
end
这里,inbuf
-full
和inbuf
-empty
分别是CCP
和KCP
的私用信号量,在过程
Send(m
)
和Read(x
)
中使用,其初值分别为0
和1
。由于在KCP
中,Send(m
)
被用
来将字符一个个地送入inbuf
中,Send(m
)
过程必须要作一定的改动,也就是要
加入缓冲计数功能和把inbuf
的长度看作是固定的。另外,outbuf
-full
和outbuf
-
empty
则是DCP
和CCP
的私用信号量,在过程receive(k
)
和write(y
)
中使用。其初
值分别为0
和1
。由于outbuf
的长度是固定的,所以receive(k
)
过程也应作相应的
修改。
109
(3) CCP
与用户进程的接口
除了和KCP
及DCP
的通信之外,CCP
还要从各用户进程那里得到提问
和向提问的用户进程转达从控制台来的指示。因此,CCP
和用户进程之
间也存在着通信关系。
设各用户进程向CCP
发出的提问,用消息组成队列RQ
。各用户进程把
消息送入RQ
时,必须互斥操作,否则将引起RQ
队列混乱。因此,设互
斥用信号量rq
,初值为1
。另外,CCP
只有在用户进程提问之后才负责
向控制台转发提问和向用户进程转达控制台的指示。因此,还必须为
CCP
设置一私用信号量question
以计算用户进程所提出的问题数目。信
号量question
的初值为0

另外,由于各用户进程在CCP
发出回答消息之后,不一定马上就能处理
CCP
所发出的回答消息,因而,需设置相应的消息接收队列SQi
。SQi
和RQ
的关系如图3.19

110
图3.19 CCP

用户进程接口
与对RQ
队列的操作时相同,对SQi
队列的操作也必须是互斥的,因
而,设互斥信号量sqi
,其初值为1
。除此之外,为了保证CCP
和各用户
进程之间在获得回答的同步,还需设一私用信号量answeri
以计算SQi

的消息个数。
CCP
和用户进程的接口可描述如下:
U-receive(m):
begin
P(question

when
rq
do
从RQ
中取出m
od
return (m)
end
Ø 这里,采用了互斥变量rq
作为临界区名。UUreceive(
m
)
描述从RQ
取出一
个消息的过程。
SSanswer(
a
,i):
begin
when
sqi
do
把a
插入SQi
中od
V(answeri

end
111
(4) CCP
的动作
作为实现用户进程与控制台通信的方法之一,利
用上面所述的各种接口,可以描述实现严格的顺
序会话CCP
进程。
会话控制进程CCP

local
k
,m
,x
repeat
U-receive(m)
将消息m
的进程标号置入k

将消息m
解码变换到x
Write(x)
Read(x)
将x
编码到m
S-answer(m
,k)
until CCP
结束
112
3.7.5
进程通信的实例——
管道
1.
管道pipe
进程通信的实用例子之一是UNIX
系统的管道通信。
UNIX
系统从System
Ⅴ开始,提供有名管道和无名管道两
种数据通信方式,这里介绍无名管道。
无名管道为建立管道的进程及其子孙提供一条以比特流
方式传送消息的通信管道。该管道在逻辑上被看作管道
文件,在物理上则由文件系统的高速缓冲区构成,而很
少启动外设。发送进程利用文件系统的系统调用
write(fd[1],buf,size)
,把buf
中的长度为size
字符的消息送
入管道入口fd[1]
,接收进程则使用系统调用
read(fd[0],buf,size)
从管道出口fd[0]
读出size
字符的消息
置入buf
中。这里,管道按FIFO
(先进先出)方式传送
消息,且只能单向传送消息(图3.20
)。
113
图3.20
管道通信
Ø利用UNIX
提供的系统调用pipe
,可建立一条同步
通信管道。其格式为:
pipe(fd
)
int
fd[2]

Ø这里,fd[1]
为写入端,fd[0]
为读出端。
114
2.
示例
例1
:用C
语言编写一个程序,建立一个pipe
,同时父进程生成一个子进程,
子进程向pipe
中写入一字符串,父进程从pipe
中读出该字符串。
解:
程序如下:
#include
〈stdio.h

main()
{
int
x
,fd[2]

char buf[30]
,s[30]

pipe(fd)

/
*
创建管道*
/
while((x=fork())==-1)

/
*
创建子进程失败时,循环*
/
if(x==0)
/
*
子进程创建成功,
并且执行子进程*
/
{
sprintf(buf
,″
This is an example
\n

)
;/
*
把字符串写入缓冲区buf
中*
/
write(fd[1]
,buf
,30)

/
*
把buf
中字符写入管道*
/
exit(0)

}
else /
*
父进程返回*
/
{
wait(0)

read(fd[0]
,s
,30)

/
*
父进程读管道中字符*
/
printf(

%s

,s)

}
}
115
例2

编写一程序,建立一个管道。同时,父进程生
成子进程P1
,P2
,这两个子进程分别向管道中写入
各自的字符串,父进程读出它们(如图3.21
)。
图3.21
父进程和子进程P
1
,P
2
通信例子
解:程序框图如图3.22
所示,源程序如下:
116
图3.22
例2
程序流图117
#include
〈stdio.h

main()
{
int
i
,r
,p1
,p2
,fd[2]

char buf[50]
,s[50]

pipe(fd)

/
*
父进程建立管道*
/
while((p1=fork())==-1)

/
*
创建子进程P1
,失败时循环*
/
if(p1==0)
 
/
*
由子进程P1
返回,执行子进程P1
*
/
{
lockf(fd[1]
,1
,??0)

/
*
加锁锁定写入端*
/
sprintf(buf
,″
child process P1 is sending messages!
\n

)

printf(

child
process P1!
\n

)

write(fd[1]
,buf
,50)

/
*
把buf
中的50
个字符写入管道*
/
sleep(5)

/
*
睡眠5
秒,让父进程读*
/
lockf(fd[1]
,0
,0)

/
*
释放管道写入端*
/
exit(0)

/
*
关闭P1
*
/
}
else /
*
从父进程返回,执行父进程*
/
{
while((p2=fork())==-1)
;/
*
创建子进程P2
,失败时循环*
/
if(p2==0) /
*
从子进程P2
返回,执行P2
*
/
{
118
lockf(fd[1]
,1
,0)

/
*
锁定写入端*
/
sprintf(buf
,″
child process P2 is sending messages
\n

)

printf(

child
process P2 !
\n

)

write(fd[1[
,buf
,50)

/
*
把buf
中字符写入管道*
/
sleep(5)

/
*
睡眠5
秒等待,
让父进程读*
/
lockf(fd[1]
,0
,0)

/
*
释放管道写入端*
/
exit(0)

/
*
关闭P2
*
/
}
wait(0)

if(r
=read(fd[0]
,s
,50)==-1)
printf(

can

t
read pipe
\n

)

else
printf(

%s
\n

,s)

wait(0)

if(r
=read(fd[0]
,s
,50)==-1)
printf(

can

t
read pipe
\n

)

else
printf(

%s
\n

,s)

exit(0)

}
}
119
Ø其中,lockf

保证进程互斥使
用管道的系统调
用,sleep
为保证
当前进程睡眠,
转让处理机的系
统调用。
§3.8




3.8.1
死锁的概念
1.
死锁的定义
各进程在使用系统资源时,应注意系统产生死锁问题。
所谓死锁,是指各并发进程彼此互相等待对方所拥有的资
源,且这些并发进程在得到对方的资源之前不会释放自己
所拥有的资源。从而造成大家都想得到资源而又都得不到
资源,各并发进程不能继续向前推进的状态。图3.23
是两个
进程发生死锁时的例子。
图3.23
死锁的概念
120
下面以生产者/
消费者问题为例来进一步看看
死锁的概念。设生产者进程已获得对缓冲区队列
的操作权,生产者进程进一步要求对缓冲区内的
某一空缓冲区进行置入消息操作。然而,设此时
缓冲队列内所有缓冲区都是满的,即只有消费者
进程才能对它们进行取消息操作。因此,生产者
进程进入等待状态。反过来,消费者进程拥有对
各缓冲区操作的操作权,为了对各缓冲区进行操
作,它又要申请对缓冲队列操作的操作权。由于
对缓冲队列的操作权被生产者进程掌握,且生产
者进程不会自动释放它,从而消费者进程也只能
进入等待状态而陷入死锁。?????????????
121
一般地,可以把死锁描述为:
有并发进程P
1
,P
2
,…
,P
n
,它们共享资源
R
1
,R
2
,…
,R
m
(n>0
0n>
,m>0
,n>=m
m>
)。其中,
每个P
i
(1
≤i
≤n
)拥有资源R
j
(1
≤j
≤m
),直
到不再有剩余资源。同时,各P
i
又在不释放R
j

前提下要求得到R
k
(k
≠j
,1
≤k
≤m
),从而造
成资源的互相占有和互相等待。在没有外力驱动
的情况下,该组并发进程停止往前推进,陷入永
久等待状态。
122
2.
死锁的起因
死锁的起因是并发进程的资源竞争。产生死
锁的根本原因在于系统提供的资源个数少于并发
进程所要求的该类资源数。显然,由于资源的有
限性,不可能为所有要求资源的进程无限制地提
供资源。但是,可以采用适当的资源分配算法,
以达到消除死锁的目的。
为此,先看看产生死锁的必要条件。
123
3.
产生死锁的必要条件
(1)
互斥条件。并发进程所要求和占有的资源是不能同时
被两个以上进程使用或操作的,进程对它所需要的资源
进行排他性控制。
(2)
不剥夺条件。进程所获得的资源在未使用完毕之前,
不能被其他进程强行剥夺,而只能由获得该资源的进程
自己释放。
(3)
部分分配。进程每次申请它所需要的一部分资源,在
等待新资源的同时继续占用已分配到的资源。
(4)
环路条件。存在一种进程循环链,链中每一个进程已
获得的资源同时被下一个进程所请求。
显然,只要使上述4
个必要条件中的某一个不满足,则
死锁就可以排除。
124
3.8.2
死锁的排除方法
解决死锁的方法一般可分为预防、避免、检测与恢复等三
种。预防是采用某种策略,限制并发进程对资源的请求,
从而使得死锁的必要条件在系统执行的任何时间都不满足。
避免是指系统在分配资源时,根据资源的使用情况提前做
出预测,从而避免死锁的发生。死锁检测与恢复是指系统
设有专门的机构,当死锁发生时,该机构能够检测到死锁
发生的位置和原因,并能通过外力破坏死锁发生的必要条
件,从而使得并发进程从死锁状态中恢复出来。
通过预防和避免的手段达到排除死锁的目的是一件十分困
难的事。死锁的检测和恢复则不必花费多少执行时间就能
发现死锁和从死锁中恢复出来。因此,在实际操作系统中
大都使用检测与恢复法排除死锁。
125
1.
死锁预防
一种方法是打破资源的互斥和不可剥夺这两个条件,例如允许进程
同时访问某些资源等。这种方法不能解决访问那些不允许被同时访
问的资源时所带来的死锁问题。另一种方法则是打破资源的部分分
配这个死锁产生的必要条件。即预先分配各并发进程所需要的全部
资源。如某个进程的资源得不到满足时,则安排一定的等待次序让
其他进程释放资源。但是,这种方法也有如下缺点:
(1)
在许多情况下,一个进程在执行之前不可能提出它所需
要的全部资源。
(2)
无论所需资源何时用到,一个进程只有在所有要求资源
都得到满足之后才开始执行。
(3)
对于那些不经常使用的资源,进程在生存过程期间一直
占用它们是一种极大的浪费。
(4)
降低了进程的并发性。
126
另外一种死锁的预防方法是打破死锁的环路条件。
即把资源分类按顺序排列,使进程在申请、保持资
源时不形成环路。如有m
种资源,则列出R
1
<R
2
<…
<R
m
。若进程Pi
保持了资源Ri
,则它只能申请
比R
i
级别更高的资源R
j
(R
i
<R
j
)。释放资源时必
须是R
j
先于R
i
被释放,从而避免环路的产生。这种
方法的缺点是限制了进程对资源的请求,而且对资
源的分类编序也耗去一定的系统开销。
127
另外一种死锁的预防方法是打破死锁的环路条件。即把资源分类按顺序排列,使进程在申请、保持资源时不形成环路。如有m种资源,则列出R1<R2<…<Rm。若进程Pi保持了资源Ri,则它只能申请比Ri级别更高的资源Rj(Ri <Rj )。释放资源时必须是Rj先于Ri被释放,从而避免环路的产生。这种方法的缺点是限制了进程对资源的请求,而且对资源的分类编序也耗去一定的系统开销。
2. 死锁避免
死锁避免可被称为动态预防,因为系统采用动态分配资源,在分配过程中预测出死锁发生的可能性并加以避免的方法。
死锁避免的一种基本模式是把进程分为多个步,其中每个步所使用的资源是固定的,且在一个步内,进程所保持的资源数不变。即进程的资源请求、使用与释放要依靠不同的步完成。
设并发进程P1,P2,…,Pn (n≥1)共享不同类型的资源R1,R2,…, Rm (m≥1),每一Ri有固定的单元数目Ci (1≤i≤n)。系统按一定的资源分配算法给各进程分配资源。
可用一向量矩阵<W,A,B,F>来描述各进程的资源请求和获得系统空闲资源的状况。其中,W=(W1,W2,…,Wn)是一个n×m维矩阵,n表示并发进程数目,m表示资源类型数目,Wij=ωi(j)是进程Pi在某一执行步时为完成任务请求追加的资源Rj的单元数目。ωi被称为进程Pi的请求向量。A=(A1,A2,…,An)是n×m维分配矩阵,Aij=ai(j)是系统分配给进程Pi的资源Rj的单元数,Ai被称为分配向量。B=(B1,B2,…,Bn)是n×m维释放矩阵,Bij=bi(j)是进程Pi释放的资源Rj的单元数。
   F=(f1,f2,…,fm)是空闲资源向量。
        设C=(c1,c2,…,cm)为系统能力向量,则有:

          即Rj类资源的空闲单元数是总单元数减去已分配给各进程的单元数。
设进程Pi可被分为k个步Pi(1),Pi(2),…,Pi(k),其中Pi(1)为初始步且Pi(k)为终止步,而且,在每一步中进程保持资源和请求资源,在每一步执行结束后进程释放资源和系统分配资源。若对于Pi(1),Pi(2),…,Pi(k)有:
 ωi(1)≤F     且 
                       
 成立,则进程P在结束序列中。如果所有并发进程都在结束序列中,则系统是安全的(无死锁)。
也就是说,进程的请求向量不能大于空闲资源和该进程准备释放的资源。这里ωi(r)表示进程Pi第r步时的请求向量。
显然,死锁回避需要占去系统较大的开销。

3.
死锁的检测和恢复
当进程进行资源请求时死锁检测算法检查
并发进程组是否构成资源的请求和保持环路。
有限状态转移图和petriNet
iterpNe
等技术都可用来有效
地判断死锁发生。死锁的恢复办法较多。最简
单的办法是终止各锁住进程,或按一定的顺序
中止进程序列,直至已释放到有足够的资源来
完成剩下的进程时为止。另外,也可以从被锁
住进程强迫剥夺资源以解除死锁。
131
§3.9
线程
3.9.1
线程的概念
进程是程序的一次执行过程和资源分配的基本单位。由此
可知,即使是同一段程序,在不同的执行时间,应属于不
同的进程。那么,什么是线程(Thread
)以及为什么在操
作系统中要引入线程的概念呢?
事实上,引入线程主要是为了提高系统的执行效率,减少
处理机的空转时间和调度切换(保护现场信息)的时间,
以及便于系统管理。
一个进程内的基本调度单位称为线程或称为轻权进程
(Light weight process
),这个调度单位既可以由操作系统
内核控制,也可以由用户程序控制。
132
可以从线程与进程的异同比较中进一步理解线程的概念。
进程是资源分配的基本单位。所有与该进程有关的资源,
例如打印机,输入缓冲队列等,都被记录在进程控制块
PCB
中。以表示该进程拥有这些资源或正在使用它们。
另外,进程也是抢占处理机的调度单位,它拥有一个完整
的虚拟地址空间(后述)。
与进程相对应,线程与资源分配无关,它属于某一个进
程,并与进程内的其他线程一起共享进程的资源。
再者,当进程发生调度时,不同的进程拥有不同的虚拟地
址空间,而同一进程内的不同线程共享同一地址空间。
133
线程只由相关堆栈(系统栈或用户栈)寄存器和线程控制
表TCB
组成。寄存器可被用来存储线程内的局部变量,但
不能存储其他线程的相关变量。
由以上可知,发生进程切换与发生线程切换时相比较,进
程切换时将涉及到有关资源指针的保存以及地址空间的变
化等问题,线程切换时,由于同一进程内的线程共享资源
和地址空间,将不涉及资源信息的保存和地址变化问题,
从而减少了操作系统的开销时间。而且,进程的调度与切
换都是由操作系统内核完成,而线程则既可由操作系统内
核完成,也可由用户程序进行。
多线程系统中进程与线程的关系如图3.24

134
图3.24
多线程与进程之间的关系
135
线




3.9.2
线程的适用范围
并不是在所有的计算机系统中线程都是适用的。事实上在
那些很少做进程调度和切换的实时系统、个人数字助理系
统中,由于任务的单一性,设置线程相反会占用更多的内
存空间和寄存器。
使用线程的最大好处是在有多个任务需要处理机处理时,
减少处理机的切换时间;而且,线程的创建和结束所需要
的系统开销也比进程的创建和结束要小得多。由此,可以
推出最适合使用线程的系统是多处理机系统。在多处理机
系统中,同一用户程序可以根据不同的功能划分为不同的
线程,放在不同的处理机上执行。
在用户程序可以按功能划分为不同的小段时,单处理机系
统也可因使用线程而简化程序的结构和提高执行效率。
136
几种典型的应用是:
服务器中的文件管理或通信控制。在局域网的文件服务器
中,对文件的访问要求可被服务器进程派生出的线程进行处
理。由于服务器同时可能接受许多个文件访问要求,则系统
可以同时生成多个线程来进行处理。如果计算机系统是多处
理机的,这些线程还可以安排到不同的处理机上执行。
(2)
前后台处理。许多用户都有过前后台处理经验,即把一个计
算量较大的程序或实时性要求不高的程序安排在处理机空闲
时执行。对于同一个进程中的上述程序来说,线程可被用来
减少处理机切换时间和提高执行速度。
(3)
异步处理。程序中的两部分如果在执行上没有顺序规定,则
这两部分程序可用线程执行。
137
另外,线程方式还可用于数据的批处理以及网络系统中的
信息发送与接收和其他相关处理等。例如,图3.25
给出了一
个用户主机通过网络向2
台远程服务器进行远程调用(RP
C)以获得相应结果的执行情况。
Ø 如果用户程序只用一个线程,则第2个远程调用的请求只
有在得到第1个请求的执行结果后才能发出。
Ø 多线程时,用户程序不必等待第1个RPC请求的执行结
果而直接发出第2个RPC请求从而缩短等
待时间。
138
(a)
单线程时的RPC
请求处理(b)
多线程时的RPC
请求处理
图3.25
139
3.9.3
线程的执行特性
线程在执行时也有它的相关特性。线程的状态和同步用来
反映线程的这些特性。
线程有3
个基本状态,即执行、就绪和阻塞。但是线程没有
进程中的挂起状态。也就是说,线程是一个只与内存和寄
存器相关的概念,它的内容不会因交换而进入外存。
针对线程的3
种基本状态,存在5
种基本操作来转换线程的
状态。这5
种基本操作是:
(1)
派生(spawn
):线程在进程内派生出来,它即可由进
程派生,也可由线程派生。用户一般用系统调用(或相应
的库函数)派生自己的线程。
一个新派生出来的线程具有相应的数据结构指针和变
量,这些指针和变量作为寄存器上下文放在相应的寄存器
和堆栈中。
新派生线程被放入就绪队列。
140
(2)
阻塞(Block
lokBc
):如果一个线程在执行过程中需要
等待某个事件发生,则被阻塞。阻塞时,寄存器上
下文、程序计数器以及堆栈指针都会得到保证。
(3)
激活(unblock
okucnbl
):如果阻塞线程的事件发生,则
该线程被激活并进入就绪队列。
(4)
调度(schedule
scedheul
):选择一个就绪线程进入执行
状态。
(5)
结束(Finish
ishnFi
):如果一个线程执行结束,它的
寄存器上下文以及堆栈内容等将被释放。
141
线程的状态和操作关系如图3.26

图3.26
线程的状态与操作
需要注意的一点是,在某些情况下,某个线程被阻
塞也可能导致该线程所属的进程被阻塞。
142
线程的另一个执行特性是同步。
由于同一进程中的所有线程共享该进程的所有资源
和地址空间,任何线程对资源的操作都会对其他相
关线程带来影响。因此,系统必须为线程的的执行
提供同步控制机制,以防止因线程的执行而破坏其
他的数据结构和给其他线程带来不利的影响。
线程中所使用的同步控制机制与进程中所使用的同
步控制机制相同。因此,这里不再进一步讲述有关
线程的同步问题。
143
3.9.4
线程的分类
线程的两个基本类型是:用户级线程和系统级线程(
核心级
线型)
。在同一个操作系统中,有的使用纯用户级线程,有
的使用纯核心级线程,例如Windows NT
sodnTNwWi
和Os/2
;有的则混
合使用用户及线程和核心级线程,例如Solaris

用户及线程(user level threads
)的管理过程全部由用户程
序完成,操作系统内核只对进程进行管理。
为了对用户级线程进行管理,操作系统提供一个在用户空
间执行的线程库。该线程库提供创建、调度、撤销线程功
能。同时该线程库也提供线程间的通信,线程的执行以及
存储线程上下文的功能。用户及线程只使用户堆栈和分配
给所属进程的用户寄存器。
144
当一个线程被派生时,线程库为其生成相应的线程控制块TCB
等数据结
构,并为TCB
中的参量赋值和把该线程置于就绪状态。其处理过程与进
程创建过程大致相似。
不同的是:
(1)
用户级线程的调度算法和调度过程全部由用户自行选择和确定,与操
作系统内核无关。在用户级线程系统中,操作系统内核的调度单位仍是
进程。如果进程的调度区间为T
,则在T
区间内,用户可以根据自己的
需要设置不同线程调度算法。
(2)
用户级线程的调度算法只进行线程上下文切换而不进行处理机切换,
且其线程上下文切换是在内核不参与的情况下进行的。也就是说,线程
上下文切换只是在用户栈、用户寄存器等之间进行切换,不涉及处理机
的状态。新线程通过程序调用指针的变化使得程序计数器变化而得以执
行。
(3)
因为用户级线程的上下文切换与内核无关,所以可能出现如下情况:
即当一个进程由于I/O
中断或时间片用完等原因造成该进程退出处理
机,而属于该进程的执行中线程仍处于执行状态。也就是说, 尽管相关
进程的的状态是阻塞的或等待的,但所属线程状态却是执行的。
145
核心级线程(Kernel-level Threads
)由操作系统内核进
行管理。操作系统内核给应用程序提供相应的系统调用
和应用程序接口API
,以使用户程序可以创建、执行、
撤消线程。
与用户线程不同,核心级线程既可以被调度到一个处理
机上并发执行,也可以被调度到不同的处理机上并行执
行。操作系统内核既负责进程的调度,也负责进程内不
同线程的调度工作。因此,核心级线程不会出现进程处
于阻塞或等待状态,而线程处于执行状态的情况。
另外,核心级线程技术也可用于内核程序自身,从而提
高操作系统内核程序的执行效率。
146
与用户级线程相比,核心级线程的上下文切换时间要大于
用户级线程的上下文切换时间。图3.27
给出了参考书[18]

给出的用户级线程、系统级线程,以及进程进行上下文切
换时的各自的时间开销。
图3.27
线程、进程等的上下文切换开销
1 840
441
37
信号等待
11 300
948
34
Null Fork
系统级进程
线程
用户级
线程
操作
147
图3.27
是在VAX
机的单处理机系统上,用UNIX
系列操作系
统测试得到的结果。由图3.27
可以看出,用户级线程占用的
系统开销最小,系统级线程的开销则较进程开销小,但要
大于用户级线程的开销。
与系统级线程相比,用户级线程的另一个优点是实现用户
级线程不需要操作系统内核的特殊支持,只要有一个能提
供线程创建、调度、执行、撤消,以及通信等功能的线程
库就行了。
有些操作系统,例如linux
或solaris2.x ,
提供用户级线程和系
统级线程两种功能。在这些操作系统中,线程的创建、调
度和同步等仍在用户空间完成,而这些线程也可被映射到
系统空间,并转化为系统级线程执行。这与后述的UNIX

户进程以及系统进程有相似之处。
148




进程是操作系统中最重要、最基本的概念之一。它是系统
分配资源的基本单位,是一个具有独立功能的程序段对某
个数据集的一次执行活动。为什么要引入进程的概念是由
操作系统的资源有限性和处理上的并行性以及系统用户的
执行起始时间的随机性所决定的。一切仅具有静态特征的
概念,例如程序不能反映系统的上述特征,因此,导入了
具有动态特征的进程概念。
149
进程具有动态性、并发性等特点。反映进程动态特性的是
进程状态的变化。进程要经历创建、等待资源、就绪准备
执行,以及执行和执行后释放资源消亡等几个过程和状态。
进程的状态转换要由不同的原语执行完成。进程的并发特
性反映在进程对资源的竞争以及由资源竞争所引起的对进
程执行速度的制约。这种制约可分为直接制约和间接制约。
进程间的直接制约是被制约进程和制约进程之间,存在着
使用对方资源的需求,只有制约进程执行后,被制约进程
才能继续往前推进。进程间的间接制约是被制约进程共享
某个一次只能供一个进程使用的系统资源,只有得到该资
源的进程才能继续往前推进,其他进程在获得资源进程执
行期间不允许交叉执行。因此,直接制约进程之间具有固
定的执行顺序,而间接制约的进程之间则没有固定的执行
顺序。
150
进程间的间接制约可利用加锁法和P,V原语操作实现。
进程间的直接制约既可用P,V原语实现,也可用其他互
相传递信号的方式实现。
尽管进程是一个动态概念,但是,从处理机执行的观点来
看,进程仍需要静态描述。一个进程的静态描述是处理机
的一个执行环境,被称为进程上下文。进程上下文由以下
部分组成:PCB(
进程控制块)
、正文段和数据段以及各种寄
存器和堆栈中的值。寄存器中主要存放将要执行指令的逻
辑地址,执行模式以及执行指令时所要用到的各种调用和
返回参数等。而堆栈中则存放CPU
现场保护信息、各种资
源控制管理信息等。
151
本章中所述的另一个重要的概念是进程通信。进程间通信又可分
为传送控制信号的低级通信和大量传送数据的高级通信。从通信
方式来看,又可分为主从式、会话式、消息与邮箱方式、以及共
享虚存方式。比较常用的死锁排除方法是检测与恢复方法。
无论是互相通信的进程或是共享某些不同类型资源的进程,都可
能因通信顺序不当或资源分配顺序不当而造成死锁。死锁是一种
因各并发进程等待资源而永久不能向前推进的系统状态。死锁对
操作系统是十分有害的,排除死锁的方法是预防、回避、检测与
恢复三种。
线程是为了提高操作系统的执行效率而引入的,它是进程内的一
段程序的基本调度单位。线程可分为用户级线程和系统级线程。
用户级线程的管理全部由线程库完成,与操作系统内核无关。线
程由寄存器、堆栈以及程序计数器等组成,同一进程的线程共享
该进程的进程空间和其他所有资源。线程主要用于多机系统以及
网络系统的操作系统中。
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值