[操作系统]管程
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
C1.signal
局部数据 进入队列 入口等待 队列
条件变量 初始化程序
条件c1队列
C1.wait
· · · · · · · · · · · ·
过程1
····· 过程n
条件cn队列
Cn.wait
队列部分
管理部分
7、利用管程解决“生产者/消费者”问题
• 定义管程名:PC • 共享的数据结构: 环形缓冲buffer ,大小为n 条件变量 notfull、notempty 环形缓冲区中产品计数:count • 设两个过程:put(item)、get(item) Producer调用→PC. put(item) →生产的产品送缓冲区 consumer调用→PC. get(item) →从缓冲区取一个产品 • 进入管程的Producer如果发现缓冲区满:count≧n →执行 notfull.wait把自己阻塞入等待不满条件队列。 • 进入管程的consumer如果发现缓冲区空:count≤0→执行 notempty.wait把自己阻塞入等待不空条件队列。
X状态:busy 忙、free 闲 封装在一个管程中 一组操作: request(X)申请、release(X) 释放 。
管程外某进程申请/释放资源时,调用request(X)或 release(X) 即可,同步与互斥由管程完成。
例如:对于进程阻塞队列(临界资源)用变量bq表示
数据结构: 队首指针、队尾指针、队列长度 封装在 一组操作: insertF(bq)、 insertL(bq)、 管程中 remove(bq)、 insert (bq)等
3、管程的结构和特性
Type 管程名=monitor 变量说明:· · · Procedure entry p1(参数) begin · · · en · · · · · · Procedure entry pn(参数) begin · · · end begin 变量初始化 end • 模块化:一个管程是一个基 本程序单位,可以单独编译;
*** 对条件变量操作进一步说明
设:条件变量为C1 C1.wait : 紧急队列非空, 则唤醒 第一个等待进程 紧急队列空,则释放互 斥权, 开放管程入口 C1.signal:
执行此操作的进 程投入C1链尾
Hoare方法
如果C1队列为空, 则相当于空操作
不空唤醒C1队列 第一个等待者
执行此操作的进程继续
• 管程机制确保一次只有一个进程在管程内活动,程 序员不需要显式地用信号量机制编写实现互斥的代 码。
2. 管程的引入
• 管程:一种同步机制,是编程的构件。 • 管程定义:
管程是关于共享资源的数据结构及一组针对该资 源的操作过程所构成的软件模块。使互斥操作相 对集中,从而增加了模块的相对独立性。
• 数据结构是资源的抽象描述 例如:对于某临界资源用共享变量X表示
notfull.signal
入口 等待 队列 局部数据:buffer in, out, count 条件变量: notfull,notempty
条件队列
notfull.wait
过程1:put(item)
过程2:get(item) 初始化程序 in=out=coun=0
notempty.signal
1、问题提出
用信号量机制编制并发程序,对共享变量、信 号量的操作(同步、互斥)被分散在各个进程 中。缺点:
•
•
易读性差:因为要了解对一组变量及信号量的 操作,需要读懂全部并发的程序。
难以修改和维护:对一组变量和代码的修改, 必须对使用它的全部程序进行修改(因为同步、 互斥分散在所有相关并发程序中。 正确性难以保证:OS通常很复杂,同步、互 斥过于分散,很难保证逻辑上的正确性。 既然分散的同步操作有缺点,人们就想到把同 步机制集中到一个模块中,这就是早期 (1971)的秘书进程思想。
····· 过程n 管理部分 · 紧急队列 队列部分
条件c1队列
队列
初始化程序
6、条件变量上的wait、signal操作
条件变量表示一种等待原因,并不取具体数值(即不 是计数器、也不是信号量)。每个原因(条件变量) 对应一个等待队列。
• 条件变量的定义: Var 变量1, 变量2, … ,变量n : condition • 对条件变量可执行wait和signal操作。对于条件变量y : y. wait将自己阻塞在y条件队列中; y . Signal可以将y队列中的一个进程唤醒。
条件队列
notempty.wait
type pc= moniter Var in,out , count :integer; buffer:array [0,…,n-1] of item; (有界缓冲区) notempty,notfull:Condition;(不空、不满两个条件) procedure entry put(item) begin if Count≥n then notfull .Wait;(满,进入等待不满条件
• 抽象数据类型:管 程中不仅有数据, 而且有对数据进行 操作的代码。
• 信息封装:管程是 半透明的,管程中
的内部过程(函数)
实现了某些功能, 至于这些功能是怎 样实现的,在其外 部则是不可见的。
管程有四部分组成
① 名称:为每个共享资源设立一个管程
② 数据结构说明:一组局部管程的控制变量
③ 操作原语:
队列)
buffer[in]:=nextp; 相当Count:=1 in : = in+1 mod n; Count : =Count+1; if notempty.queue then notempty .Signal;
end
唤醒不空条件队列一个进程
procedure entry get(item) begin if Count≤0 then notempty.Wait;(缓冲区空,等待 不空条件) nextc:=buffer[out]; out:=out+1 mod n; Count:=Count-1; if notfull.queue then notfull.Signal; end 相当Count:=n-1 begin in:=out:=Count:=0 ; (初始化) end
执行此操作的进程投入 紧急等待队列的尾部
带有紧急队列管程内部示意图
c1.signal
局部数据 进入队列 入口等待 队列 条件变量
c1.wait
条件c1队列 · · · ·
初始化程序
过程1 ····· 过程n ·
cn.wait
条件cn队列
紧急队列 (队列区)
(管理区)
按简单方法处理时管程内部示意图为:
过程n过程1初始化程序条件变量局部数据管理部分c1wait条件c1队列c1signalcnwait条件cn队列紧急队列进入队列入口等待队队列部分退出过程n过程1初始化程序条件变量局部数据管理部分c1wait条件c1队列c1signalcnwait条件cn队列紧急队列进入队列入口等待队列队列部分3管程是管理资源的资源用共享数据抽象表示因此管程内部有进程等待阻塞队列以及等待与唤醒操作这种队列称之
管程(monitor)
参看P51
OS设计中引入了信号量以后,互斥实现起来似乎很 容易,果真是这样吗?
答案是否定的!
在生产者~消费者问题中,曾提到:wait(mutex)、 wait(empty)两个语句不能对调,否则系统死锁。 说明系统的编制人员使用信号量时要特别小心。 很小的错误将产生极大的麻烦。 因为出现的错误与资源竞争、死锁、不可预测、不 可再现有关。
•
进程1请求使用共享资源
进程2请求使用共享资源 …… 进程n请求使用共享资源
Dijkstra(1971):提出“秘书”进程的思想。 Hansen和Hoare(1973):推广为“管程”。
秘 书 进 程
资源 互斥
R/W
管程基本思想:
• 把信号量及其操作原语封装在一个对象内部。(将 共享变量以及对共享变量能够进行的所有操作集中 在一个模块中)。 • 每次只允许一个进程访问管程内的资源。
条件c1队列
c1.wait
· · · · 条件cn队列
cn.wait
紧急队列 队列部分
退出
1)局部数据(共享变量)在管程外不可见,只能通过 管程内部的过程访问。 2)管程要互斥进入,其中只能有一个活动的进程。当 活动的进程 ①退出管程,或②阻塞才允许下一个 进程进入管程。
当一个进程试图进入一个被占用的管程时,在入口出等待。
被唤醒而等待的进程进入紧急等待队列。
③ 规定唤醒操作为管程各过程中最后一个可执行的语句。
—概念上更简单的方法(缺点,过程中只能有一个 唤醒操作)
2)多个进程出现在管程中 如果进程P唤醒进程Q,则P等待Q继续; C1.signal
如果进程Q在执行又唤醒进程R,则Q等待R续; …… 局部数据 C1.wait 进入队列 这时,在管程内部,由于执行唤醒操作,可能会出现多 条件变量 · · · · 入口等待 个等待进程,这些等待的进程进入紧急等待队列。 紧急等待队列优先级高于入口等待队列的优先级。 条件cn队列 过程1 Cn.wait
当进入管程的另一进程释放与某条件变量相关的资源 时,应该唤醒在该条件上等待的一个进程。
5、多个进程出现在管程中
当一个进入管程的进程执行唤醒操作时(如P唤醒Q), 管程中便存在两个同时处于活动状态的进程。
1) 处理方法有三种: 当P唤醒Q时 ① P等待Q继续,直到Q退出或等待;(Hoare方法); ② Q等待P继续,直到P等待或退出;(Hansan方法 );
教材中称之过程ห้องสมุดไป่ตู้
对控制变量和临界资源进行操作 的一组原语,是访 问该管程的唯一途径。这些原语本身是互斥的,任 一时刻只允许一个进程去调用,其余需要访问的进 程就等待。
④ 初始化代码:对控制变量进行初始化的代码
c1.signal
进入队列 入口等待队 列 局部数据 条件变量 初始化程序 过程1 ····· · 过程n 管理部分
Producer : begin repeat produce an item in nextp; pc.put(item); until false; end Consumer : begin repeat pc.get(item); consume the item in nextc; until false; end
结论:
• 用信号量实现的互斥机制,其正确性依赖于用户进 程(程序员编写的程序):
如果用户进程在进入临界区之前没有用 Wait( mutex)申请,或退出临界区时没有用 Signal( mutex)释放临界区,互斥就不能正确的实现。
• OS的工作者设计了一种靠语言编译器实现互斥正 确性的机制----管程机制。管程是编程的构件。
例如,X代表某临界资源,变量busy表示X的状态:忙、 或闲。定义一个条件变量nonbusy(等待条件不 忙) 。当进入管程的进程R/W该资源时,发现资源X 的状态为忙(busy为“忙”),则该进程: 进入等待该资源的阻塞队列→或称之进入X的等待条件 不忙队列→或称之进入nonbusy条件队列。并释放管 程的互斥权。
4、条件变量引入
c1.signal 局部数据 进入队列入口等 待队列 条件变量 初始化程序 过程1 条件c1队列 c1.wait · · · · 条件cn队列 cn.wait · 紧急队列 队列部分
·····
过程n 管理部分
• 当进入管程的进程因资源被占用等原因不能继续运行 时,使其等待。(让出CPU称之释放管程互斥权)。 • 为此在管程内部可以说明和使用一种特殊类型的变量: 条件变量。 • 每个条件变量表示一种等待原因,并不取具体数值。 每个原因对应一个等待队列。
执行的进程等待事件时
Block(bq)
调用insert(bq) 进入 阻塞 队 列
阻塞队列是一个临界资源,为各进程所共享,阻 塞进队、唤醒出队要互斥进行。在使用管程后,进队 由block(bq)调用管程中的insert(bq)过程,就 可进入阻塞队列, block(bq)设计者无须再考虑互 斥、同步问题。
例,某资源多进程共享,每次只能一个进程访问。
资源状态:用变量busy表示, 取值T、F 定义一个条件变量:nonbusy 一个进程申请使用资源: If busy then nonbusy.wait 另一个进程释放该资源: nonbusy.signal唤醒一个等不忙 条件的进程。
进入等待不忙条件队列 (进入nonbusy条件队列)
c1.signal
进入队列 入口等待 队列
条件c1队列
局部数据 条件变量 初始化程序 过程1 ····· · 过程n
管理部分
c1.wait
· · · · 条件cn队列
cn.wait
紧急队列
队列部分
3)管程是管理资源的(资源用共享数据抽象表示), 因此,管程内部有进程等待(阻塞)队列,以及等 待与唤醒操作,这种队列称之:条件队列。 4)管程是一个编程单位,相应的编译器能识别,入口 处互斥进入代码和出口退出代码由编译器自动产生。
局部数据 进入队列 入口等待 队列
条件变量 初始化程序
条件c1队列
C1.wait
· · · · · · · · · · · ·
过程1
····· 过程n
条件cn队列
Cn.wait
队列部分
管理部分
7、利用管程解决“生产者/消费者”问题
• 定义管程名:PC • 共享的数据结构: 环形缓冲buffer ,大小为n 条件变量 notfull、notempty 环形缓冲区中产品计数:count • 设两个过程:put(item)、get(item) Producer调用→PC. put(item) →生产的产品送缓冲区 consumer调用→PC. get(item) →从缓冲区取一个产品 • 进入管程的Producer如果发现缓冲区满:count≧n →执行 notfull.wait把自己阻塞入等待不满条件队列。 • 进入管程的consumer如果发现缓冲区空:count≤0→执行 notempty.wait把自己阻塞入等待不空条件队列。
X状态:busy 忙、free 闲 封装在一个管程中 一组操作: request(X)申请、release(X) 释放 。
管程外某进程申请/释放资源时,调用request(X)或 release(X) 即可,同步与互斥由管程完成。
例如:对于进程阻塞队列(临界资源)用变量bq表示
数据结构: 队首指针、队尾指针、队列长度 封装在 一组操作: insertF(bq)、 insertL(bq)、 管程中 remove(bq)、 insert (bq)等
3、管程的结构和特性
Type 管程名=monitor 变量说明:· · · Procedure entry p1(参数) begin · · · en · · · · · · Procedure entry pn(参数) begin · · · end begin 变量初始化 end • 模块化:一个管程是一个基 本程序单位,可以单独编译;
*** 对条件变量操作进一步说明
设:条件变量为C1 C1.wait : 紧急队列非空, 则唤醒 第一个等待进程 紧急队列空,则释放互 斥权, 开放管程入口 C1.signal:
执行此操作的进 程投入C1链尾
Hoare方法
如果C1队列为空, 则相当于空操作
不空唤醒C1队列 第一个等待者
执行此操作的进程继续
• 管程机制确保一次只有一个进程在管程内活动,程 序员不需要显式地用信号量机制编写实现互斥的代 码。
2. 管程的引入
• 管程:一种同步机制,是编程的构件。 • 管程定义:
管程是关于共享资源的数据结构及一组针对该资 源的操作过程所构成的软件模块。使互斥操作相 对集中,从而增加了模块的相对独立性。
• 数据结构是资源的抽象描述 例如:对于某临界资源用共享变量X表示
notfull.signal
入口 等待 队列 局部数据:buffer in, out, count 条件变量: notfull,notempty
条件队列
notfull.wait
过程1:put(item)
过程2:get(item) 初始化程序 in=out=coun=0
notempty.signal
1、问题提出
用信号量机制编制并发程序,对共享变量、信 号量的操作(同步、互斥)被分散在各个进程 中。缺点:
•
•
易读性差:因为要了解对一组变量及信号量的 操作,需要读懂全部并发的程序。
难以修改和维护:对一组变量和代码的修改, 必须对使用它的全部程序进行修改(因为同步、 互斥分散在所有相关并发程序中。 正确性难以保证:OS通常很复杂,同步、互 斥过于分散,很难保证逻辑上的正确性。 既然分散的同步操作有缺点,人们就想到把同 步机制集中到一个模块中,这就是早期 (1971)的秘书进程思想。
····· 过程n 管理部分 · 紧急队列 队列部分
条件c1队列
队列
初始化程序
6、条件变量上的wait、signal操作
条件变量表示一种等待原因,并不取具体数值(即不 是计数器、也不是信号量)。每个原因(条件变量) 对应一个等待队列。
• 条件变量的定义: Var 变量1, 变量2, … ,变量n : condition • 对条件变量可执行wait和signal操作。对于条件变量y : y. wait将自己阻塞在y条件队列中; y . Signal可以将y队列中的一个进程唤醒。
条件队列
notempty.wait
type pc= moniter Var in,out , count :integer; buffer:array [0,…,n-1] of item; (有界缓冲区) notempty,notfull:Condition;(不空、不满两个条件) procedure entry put(item) begin if Count≥n then notfull .Wait;(满,进入等待不满条件
• 抽象数据类型:管 程中不仅有数据, 而且有对数据进行 操作的代码。
• 信息封装:管程是 半透明的,管程中
的内部过程(函数)
实现了某些功能, 至于这些功能是怎 样实现的,在其外 部则是不可见的。
管程有四部分组成
① 名称:为每个共享资源设立一个管程
② 数据结构说明:一组局部管程的控制变量
③ 操作原语:
队列)
buffer[in]:=nextp; 相当Count:=1 in : = in+1 mod n; Count : =Count+1; if notempty.queue then notempty .Signal;
end
唤醒不空条件队列一个进程
procedure entry get(item) begin if Count≤0 then notempty.Wait;(缓冲区空,等待 不空条件) nextc:=buffer[out]; out:=out+1 mod n; Count:=Count-1; if notfull.queue then notfull.Signal; end 相当Count:=n-1 begin in:=out:=Count:=0 ; (初始化) end
执行此操作的进程投入 紧急等待队列的尾部
带有紧急队列管程内部示意图
c1.signal
局部数据 进入队列 入口等待 队列 条件变量
c1.wait
条件c1队列 · · · ·
初始化程序
过程1 ····· 过程n ·
cn.wait
条件cn队列
紧急队列 (队列区)
(管理区)
按简单方法处理时管程内部示意图为:
过程n过程1初始化程序条件变量局部数据管理部分c1wait条件c1队列c1signalcnwait条件cn队列紧急队列进入队列入口等待队队列部分退出过程n过程1初始化程序条件变量局部数据管理部分c1wait条件c1队列c1signalcnwait条件cn队列紧急队列进入队列入口等待队列队列部分3管程是管理资源的资源用共享数据抽象表示因此管程内部有进程等待阻塞队列以及等待与唤醒操作这种队列称之
管程(monitor)
参看P51
OS设计中引入了信号量以后,互斥实现起来似乎很 容易,果真是这样吗?
答案是否定的!
在生产者~消费者问题中,曾提到:wait(mutex)、 wait(empty)两个语句不能对调,否则系统死锁。 说明系统的编制人员使用信号量时要特别小心。 很小的错误将产生极大的麻烦。 因为出现的错误与资源竞争、死锁、不可预测、不 可再现有关。
•
进程1请求使用共享资源
进程2请求使用共享资源 …… 进程n请求使用共享资源
Dijkstra(1971):提出“秘书”进程的思想。 Hansen和Hoare(1973):推广为“管程”。
秘 书 进 程
资源 互斥
R/W
管程基本思想:
• 把信号量及其操作原语封装在一个对象内部。(将 共享变量以及对共享变量能够进行的所有操作集中 在一个模块中)。 • 每次只允许一个进程访问管程内的资源。
条件c1队列
c1.wait
· · · · 条件cn队列
cn.wait
紧急队列 队列部分
退出
1)局部数据(共享变量)在管程外不可见,只能通过 管程内部的过程访问。 2)管程要互斥进入,其中只能有一个活动的进程。当 活动的进程 ①退出管程,或②阻塞才允许下一个 进程进入管程。
当一个进程试图进入一个被占用的管程时,在入口出等待。
被唤醒而等待的进程进入紧急等待队列。
③ 规定唤醒操作为管程各过程中最后一个可执行的语句。
—概念上更简单的方法(缺点,过程中只能有一个 唤醒操作)
2)多个进程出现在管程中 如果进程P唤醒进程Q,则P等待Q继续; C1.signal
如果进程Q在执行又唤醒进程R,则Q等待R续; …… 局部数据 C1.wait 进入队列 这时,在管程内部,由于执行唤醒操作,可能会出现多 条件变量 · · · · 入口等待 个等待进程,这些等待的进程进入紧急等待队列。 紧急等待队列优先级高于入口等待队列的优先级。 条件cn队列 过程1 Cn.wait
当进入管程的另一进程释放与某条件变量相关的资源 时,应该唤醒在该条件上等待的一个进程。
5、多个进程出现在管程中
当一个进入管程的进程执行唤醒操作时(如P唤醒Q), 管程中便存在两个同时处于活动状态的进程。
1) 处理方法有三种: 当P唤醒Q时 ① P等待Q继续,直到Q退出或等待;(Hoare方法); ② Q等待P继续,直到P等待或退出;(Hansan方法 );
教材中称之过程ห้องสมุดไป่ตู้
对控制变量和临界资源进行操作 的一组原语,是访 问该管程的唯一途径。这些原语本身是互斥的,任 一时刻只允许一个进程去调用,其余需要访问的进 程就等待。
④ 初始化代码:对控制变量进行初始化的代码
c1.signal
进入队列 入口等待队 列 局部数据 条件变量 初始化程序 过程1 ····· · 过程n 管理部分
Producer : begin repeat produce an item in nextp; pc.put(item); until false; end Consumer : begin repeat pc.get(item); consume the item in nextc; until false; end
结论:
• 用信号量实现的互斥机制,其正确性依赖于用户进 程(程序员编写的程序):
如果用户进程在进入临界区之前没有用 Wait( mutex)申请,或退出临界区时没有用 Signal( mutex)释放临界区,互斥就不能正确的实现。
• OS的工作者设计了一种靠语言编译器实现互斥正 确性的机制----管程机制。管程是编程的构件。
例如,X代表某临界资源,变量busy表示X的状态:忙、 或闲。定义一个条件变量nonbusy(等待条件不 忙) 。当进入管程的进程R/W该资源时,发现资源X 的状态为忙(busy为“忙”),则该进程: 进入等待该资源的阻塞队列→或称之进入X的等待条件 不忙队列→或称之进入nonbusy条件队列。并释放管 程的互斥权。
4、条件变量引入
c1.signal 局部数据 进入队列入口等 待队列 条件变量 初始化程序 过程1 条件c1队列 c1.wait · · · · 条件cn队列 cn.wait · 紧急队列 队列部分
·····
过程n 管理部分
• 当进入管程的进程因资源被占用等原因不能继续运行 时,使其等待。(让出CPU称之释放管程互斥权)。 • 为此在管程内部可以说明和使用一种特殊类型的变量: 条件变量。 • 每个条件变量表示一种等待原因,并不取具体数值。 每个原因对应一个等待队列。
执行的进程等待事件时
Block(bq)
调用insert(bq) 进入 阻塞 队 列
阻塞队列是一个临界资源,为各进程所共享,阻 塞进队、唤醒出队要互斥进行。在使用管程后,进队 由block(bq)调用管程中的insert(bq)过程,就 可进入阻塞队列, block(bq)设计者无须再考虑互 斥、同步问题。
例,某资源多进程共享,每次只能一个进程访问。
资源状态:用变量busy表示, 取值T、F 定义一个条件变量:nonbusy 一个进程申请使用资源: If busy then nonbusy.wait 另一个进程释放该资源: nonbusy.signal唤醒一个等不忙 条件的进程。
进入等待不忙条件队列 (进入nonbusy条件队列)
c1.signal
进入队列 入口等待 队列
条件c1队列
局部数据 条件变量 初始化程序 过程1 ····· · 过程n
管理部分
c1.wait
· · · · 条件cn队列
cn.wait
紧急队列
队列部分
3)管程是管理资源的(资源用共享数据抽象表示), 因此,管程内部有进程等待(阻塞)队列,以及等 待与唤醒操作,这种队列称之:条件队列。 4)管程是一个编程单位,相应的编译器能识别,入口 处互斥进入代码和出口退出代码由编译器自动产生。