4.ipc 经典问题

Post on 03-Jan-2016

148 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

4.IPC 经典问题. ( 1 )读者写者问题 有两组并发进程 : 读者和写者 , 共享一组数据区 要求: 允许多个读者同时执行读操作 不允许读者、写者同时操作 不允许多个写者同时操作. 第一类:读者优先. 如果读者来: 1 )无读者、写者,新读者可以读 2 )有写者等,但有其它读者正在读,则新读者也可以读 3 )有写者写,新读者等 如果写者来: 1 )无读者,新写者可以写 2 )有读者,新写者等待 3 )有其它写者,新写者等待. 读者: while (true) { P(mutex); - PowerPoint PPT Presentation

TRANSCRIPT

4.IPC 经典问题

( 1 )读者写者问题 有两组并发进程 : 读者和写者 , 共享一组数据区 要求: 允许多个读者同时执行读操作 不允许读者、写者同时操作 不允许多个写者同时操作

第一类:读者优先

如果读者来:1 )无读者、写者,新读者可以读2 )有写者等,但有其它读者正在读,则

新读者也可以读3 )有写者写,新读者等如果写者来:1 )无读者,新写者可以写2 )有读者,新写者等待3 )有其它写者,新写者等待

第一类读者写者问题的解法

读者: while (true) { P(mutex); readcount ++; if (readcount==1) P (w); V(mutex); 读 P(mutex); readcount --; if (readcount==0) V(w); V(mutex); };

写者: while (true) {

P(w); 写 V(w);

};

第一类读者写者问题的解法(一般信号量集)

读者:

Swait(wmutex,1,1;

rcount,R,0);

写;Ssignal(wmutex,1);

写者:

Swait(rcount,1,1;

wmutex,1,0);

写;Ssignal(rcount,1);

增加一个限制条件:同时读的“读者”最多 R 个 Wmutex 表示“允许写”,初值是 1 Rcount 表示“允许读者数目”,初值为 R

( 2 )哲学家就餐问题

有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子

每个哲学家的行为是思考,感到饥饿,然后吃通心粉为了吃通心粉,每个哲学家必须拿到两只筷子,并且每个人只能直接从自己的左边或右边去取筷子

#define N 5

void philosopher (int i) {

while (true) {

思考; 取 fork[i]; 取 fork[(i+1) % 5] ; 进食; 放 fork[i]; 放 fork[(i+1) % 5] ; }

}

为防止死锁发生可采取的措施: 最多允许 4 个哲学家同时坐在桌子周围 仅当一个哲学家左右两边的筷子都可用时,才允许

他拿筷子() 给所有哲学家编号,奇数号的哲学家必须首先拿左

边的筷子,偶数号的哲学家则反之 为了避免死锁,把哲学家分为三种状态,思考,饥

饿,进食,并且一次拿到两只筷子,否则不拿

哲学家就餐问题解法( 1 )

#define N 5 void philosopher (int i) { while (true) { 思考; 取 fork[i]; 取 fork[(i+1) % 5] ; 进食; 放 fork[i]; 放 fork[(i+1) % 5] ; }}

哲学家就餐问题解法( 2 )

#define N 5#define THINKING 0#define HUNGRY 1#define EATING 2#typedef int semaphore;int state[N];semaphore mutex=1;semaphore s[N];

void test(int i){ if (state[ i ] == HUNGRY) && (state [ (i-1) % 5] != EATING) && (state [ (i+1) % 5] != EATING) { state[ i ] = EATING; V(&s[ i ]); } }

void philosopher (int i) { while (true) { 思考 ; P(&mutex); state[i] = HUNGRY; test(i); V(&mutex); P(&s[i]); 拿左筷子; 拿右筷子; 进食;

放左筷子; 放右筷子; P(&mutex) state[ i ] = THINKING ; test([i-1] % 5); test([i+1] % 5); V(&mutex);}}state[ i ] = THINKINGs[ i ] = 0

【作业】

1. 推广例子中的消息缓冲问题。 消息缓冲区为 k 个,有 1 个发送进

程, n 个接收进程,每个接收进程对发送来的消息都必须取一次

若有 m 个发送进程呢?

2. 第二类读者写者问题:写者优先条件:1 )多个读者可以同时进行读2 )写者必须互斥(只允许一个写者写,

也不能读者写者同时进行)3 )写者优先于读者(一旦有写者,则后

续读者必须等待,唤醒时优先考虑写者)

3. 有一个系统,定义 P 、 V 操作如下:P(s): s:=s-1; if s<0 then 将本进程插入相应队列末尾等待;V(s) : s:=s+1; if s<=0 then 从相应等待队列队尾唤醒一个进程,将其插

入就绪队列;

问题:1 )这样定义 P 、 V 操作是否有问题?2 )用这样的 P 、 V 操作实现 N 个进程竞争使用某一共享变量的互斥机制。

3 )对于 2 )的解法,有无效率更高的方法。如有,试问降低了多少复杂性?

4.理发师睡觉问题 理发店里有一位理发师,一把理发椅和

N 把供等候理发的顾客坐的椅子 如果没有顾客 , 则理发师便在理发椅上睡觉。当一个顾客到来时,他必须先唤醒理发师如果顾客到来时理发师正在理发,则如果有空椅子,可坐下来等;否则离开

5. 进程的同步机制──管程

管程的提出 采用 PV 同步机制来编写并发程序,对于

共享变量及信号量变量的操作将被分散于各个进程中

缺点:(1)易读性差,因为要了解对于一组共

享变量及信号量的操作是否正确,则必须通读整个系统或者并发程序

(2)不利于修改和维护,因为程序的局部性很差,所以任一组变量或一段代码的修改都可能影响全局

(3)正确性难以保证,因为操作系统或并发程序通常很大,要保证这样一个复杂的系统没有逻辑错误是很难的

Dijkstra(1971) :“秘书”进程Hansen 和 Hoare(1973) :管程

进程的同步机制──管程(续 1 )

管程:一种同步机制 (管程 - 类程 - 进程 )管程定义 : 指关于共享资源的数据及在其上操作的一组过程或共享数据结构及其规定的所有操作

系统按资源管理的观点分解成若干模块,用数据表示抽象系统资源,同时分析了共享资源和专用资源在管理上的差别,按不同的管理方式定义模块的类型和结构,使同步操作相对集中,从而增加了模块的相对独立性

进程的同步机制──管程(续 2 )

管程的形式

TYPE monitor_name = MONITOR;共享变量说明define 本管程内所定义、本管程外可调用的过程(函

数)名字表use 本管程外所定义、本管程内将调用的过程(函数)名字表

PROCEDURE 过程名(形参表);过程局部变量说明;BEGIN

语句序列;END;

......

FUNCTION 函数名(形参表):值类型;函数局部变量说明;

BEGIN语句序列;

END;......BEGIN

共享变量初始化语句序列;END;

管程的四个组成部分: 名称 数据结构说明 对该数据结构进行操作的一组过程 / 函数 初始化语句

管程的形式(续)

(一)模块化,一个管程是一个基本程序单位,可以单独编译(二)抽象数据类型,管程是一种特殊的数据类型,其中不仅有数据,而且有对数据进行操作的代码(三)信息掩蔽,管程是半透明的,管程中的外部过程(函数)实现了某些功能,管程中的外部过程(函数)实现了某些功能,至于这些功能是怎样实现的,在其外部则是不可见的

管程的三个主要的特性

管程有如下几个要素:(一)管程中的共享变量在管程外部是不可见的,外部只能通过调用管程中所说明的外部过程(函数)来间接地访问管程中的共享变量

(二)为了保证管程共享变量的数据完整性,规定管程互斥进入

(三)管程通常是用来管理资源的,因而在管程中应当设有进程等待队以及相应的等待及唤醒操作

管程的要素

问题:多个进程出现在管程中 当一个进入管程的进程执行等待操作时,它应当释放管程的互斥权;当一个进入管程的进程执行唤醒操作时(如P唤醒Q),管程中便存在两个同时处于活动状态的进程

处理方法有三种: P等待Q继续,直到Q退出或等待√( Hoare ) Q等待P继续,直到P等待或退出 规定唤醒为管程中最后一个可执行的操作

管程的实现——问题

因为管程是互斥进入的,所以当一个进程试图进入一个巳被占用的管程时它应当在管程的入口处等待,因而在管程的入口处应当有一个进程等待队列,称作入口等待队列

如果进程P唤醒进程Q,则P等待Q继续,如果进程Q在执行又唤醒进程R,则Q等待R继续,……,如此,在管程内部,由于执行唤醒操作,可能会出现多个等待进程,因而还需要有一个进程等待队列,这个等待队列被称为紧急等待队列。它的优先级应当高于入口等待队列的优先级

管程的实现——问题(续 1 )

由于管程通常是用于管理资源的,因而在管程内部,应当存在某种等待机制。当进入管程的进程因资源被占用等原因不能继续运行时使其等待。为此在管程内部可以说明和使用一种特殊类型的变量,称作条件变量: VAR C:condition;

对于条件型变量,可以执行wait 和 signal操作:

管程的实现——问题(续 2 )

wait ( c ):如果紧急等待队列非空,则唤醒第一个等待者;否则释放管程的互斥权,执行此操作的进程的 PCB 入 c链尾部

signal ( c ):如果 c链为空,则相当于空操作,执行此操作的进程继续;否则唤醒第一个等待者,执行此操作的进程的 PCB 入紧急等待队列的尾部

管程的实现——问题(续 3 )

管程的实现两个主要途径:* 直接构造* 间接构造,即用某种已经实现的同步机制去构造

前者效率高

例子:用 PV 操作构造管程

管程的实现

TYPE one_instance=RECORD mutex:semaphore; (初值 1 ) urgent:semaphore; (初值 0 ) urgent_count:integer; (初值 0 ) END;TYPE monitor_elements=MODULE;define enter,leave,wait,signal;

mutex (入口互斥队列) urgent (紧急等待队列) urgent_count (紧急等待队列计数)

PROCEDURE enter(VAR instance:one_instance);

BEGIN

P(instance.mutex)

END;

PROCEDURE leave(VAR instance:one_instance);

BEGIN

IF instance.urgent_count >0 THEN

BEGIN instance.urgent--;

V(instance.urgent)

END

ELSE

V(instance.mutex)

END;

PROCEDURE wait(VAR instance:one_instance;VAR s:semephore;VAR count:integer);

BEGIN

count++;

IF instance.urgent_count>0 THEN

BEGIN

instance.urgent_count--;

V(instance.urgent)

END

ELSE

V(instance. mutex);

P(s);

END;

PROCEDURE signal(VAR instance:one_instance;VAR s:semaphore;VAR count:integer);BEGIN IF count>0 THEN BEGIN count--; instance.urgent_count++; V(s); P(instance.urgent) ENDEND;

例子:一个信息缓冲区是一个共享资源 抽象成一个数据结构:数组 构造一些操作(过程或函数) 发送:向缓冲区发消息 接收:从缓冲区取消息

隐藏了内部的数据结构和实现细节

例子:读者 - 写者问题

TYPE r_and_w=MODULE;VAR instance:one_instance;rq,wq:semaphore;r_count,w_count:integer;reading_count,write_count:integer;define start_r,finish_r,start_w,finish_w;use monitor_elements.enter, monitor_elements.leave, monitor_elements.wait, monitor_elements.signal;

PROCEDURE start_r;BEGIN monitor_elements.enter(instance); IF write_count>0 THEN monitor_elements.wait (instance,rq,r_count); reading_count++; monitor_elements.signal (instance,rq,r_count); monitor_elements.leave(instance);END;

PROCEDURE finish_r;

BEGIN

monitor_elements.enter(instance);

reading_count--;

IF reading_count=0 THEN

monitor_elements.signal

(instance,wq,w_count);

monitor_elements.leave(instance);

END;

PROCEDURE start_w;

BEGIN

monitor_elements.enter(instance);

write_count++;

IF (write_count>1)

OR(reading_count>0)

THEN monitor_elements.wait

(instance,wq,w_count);

monitor_elements.leave(instance);

END;

BEGIN

reading_count::=0;

write_count::=0;

r_count:=0;

w_count::=0;

END;

读者的活动:r_and_w.start_r;

读操作;r_and_w.finish_r;

写者的活动:r_and_w.start_w;

写操作;r_and_w.finish_w;

管程和进程的异同点:( 1 )设置进程和管程的目的不同( 2 )系统管理数据结构 进程: PCB 管程:等待队列( 3 )管程被进程调用( 4 )管程是操作系统的固有成分,无创建和撤消

管程与进程

四、进程通信

概述 消息缓冲通信方式

1.概述

P.V 操作实现的是进程之间的低级通讯,所以 P.V 为低级通讯原语。它只能传递简单的信号,不能传递交换大量信息

如果要在进程间传递大量信息则要用 Send / Receive原语(高级通讯原语)

( 1 )进程通信的方式

共享内存: 相互通信的进程间设有公共内存,一组进

程向该公共内存中写,另一组进程从公共内存中读,通过这种方式实现两组进程间的信息交换

这种通信模式需要解决两个问题?

消息传递:系统为进程提供了两个高级通讯原语 send

和 receive send :

当要进行消息传递时执行 send receive :

当接收者要接收消息时执行 receive

进程通信的方式(续 1 )

消息传递模式: 消息缓冲 在内存中开设缓冲区,发送进程将消

息送入缓冲区,接收进程接收传递来的缓冲区

信箱通信

进程通信的方式(续 2 )

共享文件模式:管道通信

进程通信的方式(续 3 )

直接通信和间接通信

直接通信:信息直接传递给接收方,如管道 在发送时,指定接收方的地址或标识,也可以指定多个接收方或广播式地址

在接收时,允许接收来自任意发送方的消息,并在读出消息的同时获取发送方的地址

间接通信:借助于收发双方进程之外的共享数据结构作为通信中转,如消息队列。通常收方和发方的数目可以是任意的

2. 消息缓冲

(有界缓冲区原理): 在操作系统空间设置一组缓冲区,当发送

进程需要发送消息时,执行 send 系统调用,产生自愿性中断,进入操作系统,操作系统为发送进程分配一个空缓冲区,并将所发送的消息从发送进程 copy 到缓冲区中,然后将该载有消息的缓冲区连接到接收进程的消息链链尾,如此就完成了发送过程。发送进程返回到用户态继续执行

消息缓冲(续 1 )

(有界缓冲区原理):

在以后某个时刻,当接收进程执行到 receive 接收原语时,也产生自愿性中断进入操作系统,由操作系统将载有消息的缓冲区从消息链中取出,并把消息内容 copy到接收进程空间,之后收回缓冲区,如此就完成了消息的接收,接收进程返回到用户态继续进行

PCB

......Send(R, M)

......SIZE: 消息长度TEXT: 消息正文

......消息链指针

......

......Receive(pid, N)

......SIZE: 消息长度TEXT: 消息正文

......M: N:

接收进程 R发送进程 S

消息

消息

消息

......

消息缓冲区结构: 消息长度 消息正文 发送者 消息队列指针

消息缓冲(续 2 )

用 P.V 操作来实现Send原语 :Send ( R ,M) P(m-mutex);Begin 把缓冲区挂到接收进程 根据 R找接收进程, 的消息链链尾 ; 如果没找到出错返回 ; V(m-mutex); 申请空缓冲区 P ( s-b); V(s-m); P(b-mutex); END 摘空缓冲区 ; V(b-mutex); 把消息从M处 copy 到空缓冲区 ;

其中 s-b初值 :n ;s-m初值 :0

消息缓冲(续 3 )

3. 信箱通信

信箱组成信箱说明 与 信箱体可存放信件数,已存放信件数,指针 信箱使用规则 若发送信件时信箱已满,则发送进程被置为

“等信箱”状态,直到信箱有空时才被释放 若取信件时信箱中无信,则接收进程被置为

“等信件”状态,直到有信件时才被释放

信箱通信(续 1 )

Send实现send ( N , M ):把信件 M 送到指定的信箱 N 中步骤:查找指定信箱 N ;若信箱未满,则把信件 M 送入信箱且释放“等信件”

者;若信箱已满置发送信件进程为“等信箱”状态;

信箱通信(续 2 )

Receive实现receive ( N , X ):从指定信箱 N 中取出一封信,存放到指定的地址 X 中步骤:查找指定信箱 N ;若信箱中有信,则取出一封信存于 X 中且释放“等

信箱”者;若信箱中无信件则置接收信件进程“等信件”状态;

3. 信箱通信(续 3 )

应用实例磁盘管理进程:从信箱中收取信件,处理,启动磁盘工作

其他进程:要求访问磁盘,向磁盘管理进程发一封信

作业: 用进程通信的办法解决生产者消费者问题

4. 管道通信方式 Pipe

也称共享文件方式,基于文件系统,利用一个打开的共享文件连接两个相互通信的进程,文件作为缓冲传输介质

发送进程 接收进程

字符流方式写入读出先进先出顺序

5. 高级通信的特征

通信链路: 点对点 /多点 /广播 单向 /双向 有容量(链路带缓冲区) /无容量(发送方和接收方需自备缓冲

区) 数据格式:

字节流:各次发送之间的分界,在接收时不被保留,没有格式 报文:各次发送之间的分界,在接收时被保留,通常有格式(如表示类型),定长 /不定长报文,可靠报文 /不可靠报文

收发操作的同步方式 发送阻塞(直到被链路容量或接收方所接受)和不阻塞(失败时立即返回)

接收阻塞(直到有数据可读)和不阻塞(无数据时立即返回) 由事件驱动收发:在允许发送或有数据可读时,才做发送和接收

操作

五、处理机调度( CPU调度)

要解决的问题WHAT :按什么原则分配CPU —进程调度算法WHEN :何时分配CPU —进程调度的时机HOW: 如何分配CPU —CPU调度过程(进程的上下文切换)

处理机调度的三个层次

处理机是计算机系统中的重要资源处理机调度算法对整个计算机系统的综合性能指标有重要影响

可把处理机调度分成三个层次:

高级调度 中级调度 低级调度

高级调度也称为作业调度或宏观调度 高级调度的时间尺度通常是分钟、小时或天 中级调度涉及进程在内外存间的交换,从存储器资源管理的角度来看,把进程的部分或全部换出到外存上,可为当前运行进程的执行提供所需内存空间,将当前进程所需部分换入到内存。指令和数据必须在内存里才能被处理机直接访问

低级调度也称微观调度,从处理机资源分配的角度来看,处理机需要经常选择就绪进程或线程进入运行状态,低级调度的时间尺度通常是毫秒级的。由于低级调度算法的频繁使用,要求在实现时做到高效

处理机调度的三个层次(续)

1.处理机调度算法

( 1 )处理机调度 处理机调度的任务是控制协调进程对 C

PU 的竞争即按一定的调度算法从就绪队列中选中一个进程,把 CPU 的使用权交给被选中的进程

( 2 )确定算法的原则

具有公平性 资源利用率高(特别是 CPU利用率) 在交互式系统情况下要追求响应时间

(越短越好) 在批处理系统情况下要追求系统吞吐量

( 3 )各种进程调度算法

先进先出进程调度算法( FIFO ) 按照进程就绪的先后次序来调度进程 优点 :实现简单 缺点 :没考虑进程的优先级

基于优先数的调度( HPF—Highest Priority First )

优先选择就绪队列中优先级最高的进程投入运行

优先级根据优先数来决定

各种进程调度算法(续 1 )

确定优先数的方法静态优先数法: 在进程创建时指定优先数,在进程运行时

优先数不变动态优先数法: 在进程创建时创立一个优先数,但在其生命周期内优先数可以动态变化。如等待时间长优先数可改变

各种进程调度算法(续 2 )

两种占用 CPU 的方式:可剥夺式(可抢占式 Preemptive ): 当有比正在运行的进程优先级更高的进程就绪

时,系统可强行剥夺正在运行进程的 CPU ,提供给具有更高优先级的进程使用

不可剥夺式(不可抢占式 Non-preemptive ): 某一进程被调度运行后,除非由于它自身的原因不能运行,否则一直运行下去

各种进程调度算法(续 3 )

时间片轮转程序调度算法(RR—Round Robin)

把 CPU划分成若干时间片 , 并且按顺序赋给就绪队列中的每一个进程,进程轮流占有 CPU ,当时间片用完时,即使进程未执行完毕,系统也剥夺该进程的 CPU ,将该进程排在就绪队列末尾。同时系统选择另一个进程运行

各种进程调度算法(续 4 )

分时系统中常用时间片轮转法:时间片选择问题: 固定时间片 可变时间片与时间片大小有关的因素: 系统响应时间 就绪进程个数 CPU 能力

各种进程调度算法(续 5 )

多队列反馈调度算法 将就绪队列分为 N级,每个就绪队列分配给

不同的时间片,队列级别越高,时间越长,级别越小,时间片越小,最后一级采用时间片轮转,其他队列采用先进先出; 系统从第一级调度,当第一级为空时,系统转向第二个队列, ..... 当运行进程用完一个时间片,放弃 CPU 时,进入下一级队列;等待进程被唤醒时,进入原来的就绪队列;当进程第一次就绪时,进入第一级队列

各种进程调度算法(续 6 )

* 首先系统中设置多个就绪队列* 每个就绪队列分配给不同时间片,优先级高的为第一级

队列,时间片最小,随着队列级别的降低,时间片加大* 各个队列按照先进先出调度算法* 一个新进程就绪后进入第一级队列* 进程由于等待而放弃 CPU 后,进入等待队列,一旦等待

的事件发生,则回到原来的就绪队列* 当有一个优先级更高的进程就绪时,可以抢占CPU ,被抢占进程回到原来一级就绪队列末尾

* 当第一级队列空时,就去调度第二级队列,如此类推* 当时间片到后,进程放弃 CPU ,回到下一级队列

各种进程调度算法(续 7 )

2. 进程调度的时机 当一个进程运行完毕,或由于某种错误而终止运行

当一个进程在运行中处于等待状态(等待 I/O)

分时系统中时间片到 当有一个优先级更高的进程就绪(可抢占式) 例如:新创建一个进程,一个等待进程变成就绪

在进程通信中,执行中的进程执行了某种原语操作( P 操作,阻塞原语,唤醒原语)

3. 进程切换 进程切换 一个进程让出处理器,由另一个进程占用处理器的过程 进程的切换使系统中的各进程均有机会占用 CPU 进程的切换是由进程状态的变化引起的,而进程状态的变化又与出现中断事件有关

当有中断事件发生时,当前运行的进程被中断,中断响应后由操作系统处理出现的中断事件。中断处理后,某些进程的状态会发生变化,也可能又创建了一些新的进程。因此,要进行队列的调整。然后,进程调度根据预定的调度算法从就绪队列选一个进程占用 CPU。这个占用 CPU运行的进程可能仍是被中断的进程,也可能是另一个进程

何时切换进程 ? 只要 OS 取得对 CPU 的控制,进程切换就

可能发生,如 : 超级用户调用

来自程序的显式请求 (如:打开文件 ), 该进程通常会被阻塞

陷阱 最末一条指令导致出错,会引起进程移至退出状态

中断 外部因素影响当前指令的执行,控制被转移至 IH(中断处理程序)

中断的例子

时钟 进程用完其时间片,被转换至就绪状态

I/O 先前等待该事件的进程被转换为就绪 (或就绪挂起 )状态

然后重新运行该进程或选择一更高优先级的进程 存储器因素

内存地址是在虚拟存储器中,它必须把对应的存储块调入主存

于是相应的进程成为阻塞状态 (等待 I/O 完成 )

4.CPU调度过程

* 保存现场:顺序保存,最后一步保存 PSW* 选择要运行的程序 (如果没有就绪进程 , 系统会安排一个闲逛

进程 (idle),没有其他进程时该进程一直运行 , 在执行过程中可接收中断)* 恢复现场:最后一步恢复选中进程的 PSW

在进程(上下文)中切换的步骤 保存处理器的上下文,包括程序计数器和其它寄存器

用新状态和其它相关信息更新正在运行进程的PCB

把原来的进程移至合适的队列 - 就绪、阻塞 选择另一个要执行的进程 更新被选中进程的 PCB 从被选中进程中重装入 CPU 上下文

六、系统核心

系统核心:向上提供多个无中断的虚拟机器在核心内不允许中断

特点: * 为进程运行提供一个舞台 * 核心常驻内存 * 设计短小精焊

1.核心的组成

中断处理 进程管理 : 调度 控制 通讯 互斥 同步等 原语管理 : 在核心中提供一系列原语,同步 , 通信,创建,撤消等

队列管理

队列数据结构 :指向队首的表指针 三个队列 : 运行,就绪,等待队列 排队方式 : 排队首 排队尾 插 队 出队方式 : 队首出队 /队中出队 队列管理 : 中断之后,进程调度之前

现场管理

保存现场 ;注意顺序 , 中断之后第一步 恢复现场 :恢复时机,进程调度最后一步 时钟管理 : 以固定频率 +1 -1 用途 : 进入绝对时钟 间隔时钟 进行分析比较

虚时钟

每个进程分配给一个虚时钟来记录 CPU时间 ,这个时钟称为虚时钟

虚时钟存放在 PCB中,属于现场的一部分,进程运行时,将虚时钟放入内存开辟的专门单元,离开CPU 则放在 PCB中

2.核心处理流程

进入核心的唯一入口 : 中断中断后进入核心,由硬件完成

3.内核的执行特点

由中断驱动的 : 中断→内核→退出内核执行是连续的内核执行过程中在中断屏蔽状态下内核使用特权指令

七、线程的基本概念

线程的引入线程与进程的对比线程的实现实例: Solaris

1.线程的引入

进程的两个基本属性: 资源的拥有者: 给每个进程分配一虚拟地址空间,保存进

程映像,控制一些资源(文件, I/O设备),有状态、优先级、调度

调度单位: 进程是一个执行轨迹 以上两个属性构成进程并发执行的基础

线程的引入(续 1 )

系统必须完成的操作: 创建进程 撤消进程 进程切换

缺点: 时间空间开销大,限制并发度的提高

线程的引入(续 2 )

在操作系统中,进程的引入提高了计算机资源的利用效率。但在进一步提高进程的并发性时,人们发现进程切换开销占的比重越来越大,同时进程间通信的效率也受到限制

线程的引入正是为了简化线程间的通信,以小的开销来提高进程内的并发程度

线程的引入(续 3 )

线程:有时称轻量级进程 进程中的一个运行实体 是一个 CPU调度单位 资源的拥有者还是进程或称任务

将原来进程的两个属性分开处理

线程的引入(续 4 )

线程: 有执行状态(状态转换) 不运行时保存上下文 有一个执行栈 有一些局部变量的静态存储 可存取所在进程的内存和其他资源 可以创建、撤消另一个线程

线程和进程:单进程、单线程单进程、多线程多进程、一个进程一个线程多进程、一个进程多个线程

P C B用户栈

单线程进程模型

用户地址空间核心栈

线程控制块:包含了寄存器映像,线程优先数和线程状态信息

P C B

多线程进程模型

用户地址空间

用户栈

核心栈

线程控制块

用户栈

核心栈

线程控制块

用户栈

核心栈

线程控制块

引入线程的好处

创建一个新线程花费时间少(结束亦如此) 两个线程的切换花费时间少 (如果机器设有“存储 [恢复 ] 所有寄存器”指令,则整个切换过程用几条指令即可完成)

因为同一进程内的线程共享内存和文件,因此它们之间相互通信无须调用内核

适合多处理机系统

例子 1

LAN 中的一个文件服务器,在一段时间内需要处理几个文件请求

因此有效的方法是:为每一个请求创建一个线程

在一个 SMP机器上:多个线程可以同时在不同的处理器上运行

例子 2

一个线程显示菜单,并读入用户输入;另一个线程执行用户命令

考虑一个应用:由几个独立部分组成,这几个部分不需要顺序执行,则每个部分可以以线程方式实现

当一个线程因 I/O阻塞时,可以切换到同一应用的另一个线程

2.线程与进程的比较

调度 并发性拥有资源 系统开销

3.线程的实现机制

用户级线程核心级线程 两者结合方法

( 1 )用户级线程( User Level Thread )

由应用程序完成所有线程的管理 通过线程库 ( 用户空间 ) 一组管理线程的过程 核心不知道线程的存在

线程切换不需要核心态特权

调度是应用特定的

线程库

创建、撤消线程 在线程之间传递消息和数据 调度线程执行 保护和恢复线程上下文

对用户级线程的核心活动

核心不知道线程的活动,但仍然管理线程的进程的活动

当线程调用系统调用时,整个进程阻塞 但对线程库来说,线程仍然是运行状态 即线程状态是与进程状态独立的

用户级线程的优点和缺点

优点: 线程切换不调用核心 调度是应用程序特定的:可以选择最好的算法 ULT 可运行在任何操作系统上(只需要线程库)缺点: 大多数系统调用是阻塞的,因此核心阻塞进程,故进程中所有线程将被阻塞

核心只将处理器分配给进程,同一进程中的两个线程不能同时运行于两个处理器上

( 2 )核心级线程( KLT )

所有线程管理由核心完成 没有线程库,但对核心线程工具提供 API 核心维护进程和线程的上下文 线程之间的切换需要核心支持 以线程为基础进行调度 例子:Windows 2000/XP

核心级线程的优点和缺点

优点: 对多处理器,核心可以同时调度同一进程

的多个线程 阻塞是在线程一级完成 核心例程是多线程的缺点: 在同一进程内的线程切换调用内核,导致速度下降

( 3 )两者分析

针对不同的操作系统 开销和性能(线程的调度和切换速度线程的调度和切换速度) 系统调用(阻塞阻塞) 线程执行时间 灵活性 可扩充性 抢占CPU 共享进程的资源

( 4 ) ULT 和 KLT结合方法

线程创建在用户空间完成 大量线程调度和同步在用户空间完成 程序员可以调整 KLT 的数量 可以取两者中最好的 例子: Solaris

4.实例: Solaris

进程: 用户地址空间 用户栈 进程控制块

实例: Solaris (续 1 )

用户级线程(线程库): 可在应用进程中建立多个 ULT 每个 ULT需要:栈、程序计数器 不受调度程序的调度,线程切换快 对操作系统不可见 提供应用程序并行性接口

实例: Solaris (续 2 )

核心级线程: 设置了大量 KLT 有一个小的数据结构和栈 完成内核的所有工作 调度处理器的单位,其结构由核心维护

实例: Solaris (续 3 )

轻型进程( LWP ): 每个 ULT利用 LWP与内核通信 每个 LWP支持一个或多个用户级线程,

并映射到一个核心级线程 每个 LWP 对应用程序可见,内核看到的

是多个 LWP而看不到 ULT

Solaris :

如果逻辑并行性不需要硬件并行性的支持,则可使用 ULT

例子:多个窗口,任一时刻只有一个窗口是活跃的

如果内核级线程可能被阻塞,则可以指定两个或多个 LWP ,避免整个应用程序的阻塞

分派

唤醒继续

抢占

停止

可运行

睡眠

睡眠

停止

停止

停止

用户级线程

活跃

连接在 LWP上

分派 唤醒

继续

时间片或抢占

停止

运行

阻塞系统调用

停止

停止

轻型进程状态

LWP 状态独立于状态 ULT(受限制 ULT除外)

可运行

阻塞

唤醒

进程 1 进程 2 进程 3 进程 4 进程 5

进程库用户

内核

硬件

用户级线程 内核级线程 轻型线程 处理器

top related