进程管理
一 、 进程与PCB
2.1 进程的基本概念
关于程序执行顺序
前趋图:
(1) 顺序性
处理机的操作严格按程序规定顺序执行
(2) 封闭性
程序一旦开始执行,其计算结果不受外界因素影响。
(3) 可再现性
程序执行只要初始条件一样,不论如何停顿,重复执行多少次结果都一样。
不可再现结果的并发无意义
失去封闭性:共享资源,资源状态由多道程序改变,程序运行失去封闭性。即程序运行受其他程序的影响。
结果不可再现性
程序:程序段 + 数据段
进程实体:程序段 + 数据段 + 控制块PCB
进程:进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。
进程的特征
结构性特征,进程的根本——PCB
动态性
进程实质上是进程实体的一次有生命期的执行过程。程序只是静态的一组有序指令。
进程最基本特征
并发性
多个进程实体同存于内存中,在一段时间内同时运行。
有PCB的程序才能并发。
独立性
异步性
进程的基本状态
(1)就绪状态
进程获得除CPU之外的所有必需资源,一旦得到CPU控制权,可立即运行。
(2)运行状态
进程已获得所有运行必需的资源,正在处理机上执行。
(3)阻塞状态
正在执行的进程由于发生某事件(请求I/O、申请缓冲、时间片到)而暂时无法执行时,便放弃CPU后暂停
状态转化图:
进程控制块PCB
进程实体:代码段+数据段+PCB
进程控制块是进程存在的唯一标志:
进程创建时,PCB建立并伴随进程运行的全过程,直到进程撤消而撤消。PCB就象我们的户口。
进程标识符信息
处理机状态信息
进程调度信息
进程控制信息
PCB的组织方式
链接方式
索引方式
2.2进程控制与同步
进程的创建
进程的终止
进程的阻塞与唤醒
进程的挂起和激活
2.3 进程同步
进程同步的主要任务: 使并发执行的诸进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性 临界资源
临界资源
一次仅允许一个进程使用的资源
互斥:在操作系统中,当一个进程进入临界区使用临界资源时,另一个进程必须等待,直到占用临界资源的进程退出临界区,我们称进程之间的这种相互制约关系为“互斥”。
同步:多个相互合作的进程,在一些关键点上可能需要互相等待或互相交换信息,这种相互制约关系称为进程同步关系。可理解为“有序”。
临界区
每个进程中访问临界资源的那段代码叫临界区。为了正确同步,对临界区的代码要增加控制
同步机制应遵循的规则
空闲让进:资源使用最基本原则
忙则等待:保证互斥
有限等待:合适时被唤醒防止死等
让权等待:能主动释放CPU防止忙等
同步控制的关键:判断”和”修改标志”操作
2-3 信号量机制
整型信号量:信号量定义为一个整型量;根据初始情况赋相应的值;仅能通过两个原子操作来访问。
P操作 wait(S):
While S<=0 do no-op;
S:=S-1;
V操作 signal(S):
S:=S+1;
记录型信号量:整型信号量符合“有限等待”原则;整型信号量不符合“让权等待”原则
P操作wait():
S.value = S.value - 1;
if S.value < 0 then block(S,L)
V操作signal():
S.value = S.value + 1;
if S.value <= 0 then wakeup(S,L)
司机:
Repeat
P(s1);
离站;
行车;
到站;
V(s2);
Until false;
售票员:
Repeat
关车门;
V(s1);
售票;
P(s2);
开车门;
乘客上下车;
Until false;
2-4 经典同步问题
生产者—消费者问题
semaphore mutex=1; //临界区互斥信号量
semaphore empty=n; //空闲缓冲区
semaphore full=0; //缓冲区初始化为空
producer ()//生产者进程
{
while(1)
{
produce an item in nextp; //生产数据
P(empty); //获取空缓冲区单元
P(mutex); //进入临界区.
add nextp to buffer; //将数据放入缓冲区
V(mutex); //离开临界区,释放互斥信号量
V(full); //满缓冲区数加1
}
}
consumer ()//消费者进程
{
while(1)
{
P(full); //获取满缓冲区单元
P(mutex); // 进入临界区
remove an item from buffer; //从缓冲区中取出数据
V (mutex); //离开临界区,释放互斥信号量
V (empty) ; //空缓冲区数加1
consume the item; //消费数据
}
}
哲学家就餐问题
semaphore chopstick[5]={1,1,1,1,1};
semaphore room=4;
void philosopher(int i)
{
while(true)
{
think();
wait(room); //请求进入房间进餐
wait(chopstick[i]); //请求左手边的筷子
wait(chopstick[(i+1)%5]); //请求右手边的筷子
eat();
signal(chopstick[(i+1)%5]); //释放右手边的筷子
signal(chopstick[i]); //释放左手边的筷子
signal(room); //退出房间释放信号量room
}
}
读者——写者问题
semaphore Wmutex, Rmutex = 1;
int Rcount = 0;
void reader() /*读者进程*/
{
while(true)
{
P(Rmutex);
if(Rcount == 0) P(wmutex);
Rcount= Rcount + 1;
V(Rmutex);
⋯⋯;
read;/* 执行读操作 */
⋯⋯;
P(Rmutex);
Rcount= Rcount - 1;
if(Rcount == 0) V(wmutex);
V(Rmutex);
}
}
void writer() /*写者进程*/
{
while(true)
{
P(Wmutex);
⋯⋯;
write;/* 执行写操作 */
⋯⋯;
P(Wmutex);
}
}