目录
- 第一章 绪论
- 第二章 用户接口和操作管理
- 第三章 进程管理
-
- 一、概述
- 二、过程描述
- 三、过程控制
- 四、线程
- 五、过程互斥同步
- 六、进程间通信
- 七、死锁问题
- 第四章 处理机调度
-
- 一、分级调度
- 二、作业调度
- 三、过程调度
- 四、调度算法
- 五、实时调度
- 六、多处理机调度
- 第五章 存储管理
-
- 一、存储管理的目标和功能
- 二、分区存储管理
- 三、覆盖和交换技术
- 四、页式和段式存储管理
- 五、虚拟存储器
- 第六章 文件系统
-
- 一、文件和文件系统
- 二、文件的逻辑结构
- 三、外存分配方式
- 四、目录管理
- 五、文件存储空间管理
- 六、文件共享和文件保护
- 第七章 设备管理
-
- 一、I/O设备
- 二、I/O控制方式
- 三、缓冲技术
- 四、设备分配与回收
- 5.磁盘存储器的管理
第一章 绪论
1.操作系统的状态:接近系统硬件,在所有其他软件下,是其他软件的共同环境 2.操作系统的定义:操作系统是计算机系统中的系统软件,它是一些程序模块的集合——它们可以尽可能有效和合理,合理地,并,使用户能够灵活、方便、有效地使用计算机,使整个计算机系统能够高效地运行,是计算机与用户之间的界面。 3.操作系统的功能: (1) 处理机管理:完成等功能。 (2) 存储管理:提高利用率,方便用户使用,提供足够的存储空间,方便过程并发运行。内存的分配、保护和扩展。 (3) 设备管理:方便设备使用,改进CPU和I/O设备利用率。 (4) 信息管理:解决软件资源的存储、共享、保密和保护。 (5) 用户接口:提供友好的用户访问操作系统接口。 4.操作系统的特点: (1) 并发:计算机系统中同时存在多个程序,宏观上是同时向前推进的。(并发:同间段;并行:同一时间) (2) 共享:多个过程共享有限的计算机系统资源,操作系统合理分配和使用系统资源,资源在一段时间内交替用于多个过程。(共享和访问) (3) 虚拟:物理实体映射是操作系统管理系统资源的重要手段,可以提高资源利用率。 (4) 异步:执行顺序和执行时间的不确定性。
第二章 用户接口和操作管理
1.程序启动方式: (1) 命令方式:在命令提示符下输入命令,返回车辆执行。 (2) 批处理方法:以命令的形式启动执行批文件,依次执行批文件中的命令。 (3) EXEC方法:在一个程序中操作另一个程序。 (4) 执行硬件装入程序和启动程序 (5) 自启程序:自己装入自己,执行程序。(由指导程序和程序主体组成) 2.作业的基本概念: (1) 从用户的角度来看:在应用程序业务处理过程中,用户要求计算机从输入开始到输出结束所做的所有工作。(操作由不同顺序的操作步骤组成) (2) 从系统的角度: 3.建立作业 (1) 操作输入:将操作程序、数据和操作说明书从输入设备输入到外存,并形成初始信息。 ①在线输入(预输入):外围设备与主机直接连接。 ②脱机输入方式:采用低档个人计算机作为外围处理机进行输入处理。 ③直接耦合:通过公共大容量外存直接耦合主机和外围低档机。 ④SPOOLING系统:假脱机。 ⑤网络输入模式:用户需要将计算机网络中某个主机输入的信息传输到同一网络中的另一个主机进行操作或执行。 (2) 作业控制块(JCB)建立:建立操作时,系统应根据操作说明书建立JCB。 4.用户接口 (1) 程序级接口:系统设置为用户在程序级提供相关服务命令组成。 (2) 操作级接口:为用户提供各种服务。(脱机方式:用户在系统执行过程中不能干预(批处理);在线方式:用户直接参与控制操作执行) (3) 图形用户界面 5. 相同点: (1) 改变指令流程 (2) 重复执行和公用 (3) 改变指令流程后,需要返回原处 不同点: (1) 在不同的系统状态下运行:一般过程调用,调用程序和调用程序在同一状态(用户状态)运行;系统调用时,调用程序处于用户状态,调用程序处于系统状态(核心状态)。 (2) 通过软中断进入:一般调用过程直接从调用过程转向调用过程;系统调用必须通过系统调用指令从软中断转向相应的处理程序,CPU从用户态到系统态。 (3) 返回问题:一般调用过程在调用过程完成后直接返回调用过程;调用过程完成后,系统调用必须优先分析系统中所有要求的操作过程。
第三章 进程管理
一、概述
1.流程执行: (1) 顺序执行:单道批处理系统的执行模式,具有独立功能的程序独家CPU直到得到最终结果的过程。 ①顺序性 ②封闭:独占所有资源,计算机的状态仅由程序的控制逻辑决定。 ③可再现性:初始条件相同,结果相同。 (2) 并发执行:一组逻辑上独立的程序或程序段在执行时间上客观重叠(一个程序或程序段的执行尚未结束,另一个程序或程序段的执行已经开始)。 ①间歇性(异步性):一个程序可能会中途停止,失去原来的时序关系。 ②失去封闭性:共享资源受其他程序控制逻辑的影响。 ③在程序的两次执行过程中,外部环境发生了变化。 2.并发执行条件:封闭可再现。 3.过程定义:一个具有一定独立功能的程序在数据集中一次过程。(过程是程序的执行活动) 4.工艺特点: (1) 动态:动态产生过程。 (2) 独立性:每个过程,除非采用进程间通信。 (3) 并发性:任何过程都可以与其他过程一起推进。 (4) 异步性:每个过程都以相对独立和不可预测的速度前进。 (5) 结构化:过程=代码段 数据段 PCB 5.: (1) 过程是动态的,程序是静态的。 (2) 进程是暂时的,程序是永久的。进程是一个状态变化的过程,程序可长久保存。 (3) 不同的组成:程序、数据和PCB。 (4) 对应关系:通过多次执行,一个程序可以对应多个过程;通过调用关系,一个过程可以包括多个程序。 (5) 该过程具有并发特征,没有程序。 (6) 流程是计算机资源竞争的基本单位。
二、过程描述
1.过程组成:过程=程序 数据 进程控制块PCB 2.进程控制块PCB:过程的控制结构是过程的唯一标志。 (1) PCB全部或部分全部或部分结构。 (2) PCB随过程的创建而填写,随过程的撤销而释放。 (3) 系统利用PCB控制和管理过程,PCB它是系统感知过程存在的唯一标志。 (4) 进程与PCB一一对应。 3.过程上下文:静态描述整个过程执行活动。 (1) 用户级上下文地址空间,包括用户文本段、用户数据段和用户堆栈。 (2) 寄存器级别:程序寄存器、处理器状态寄存器、栈指针、通用寄存器的值。 (3) 系统级上下文:静态部分(PCB和资源表),动态部分(核心栈)。 4.PCB的组织方式 (1) PCB表 ①系统把所有PCB它们组织在一起,放在内存的固定区域,形成PCB表。 ②PCB表的大小决定了系统中最多可同时存在的进程个数,称为系统的并发度。 (2) 链表:同一状态的过程PCB多个状态对应于多个不同的链表(就绪链表、阻塞链表)。 (3) 索引表:同一状态的过程分为一个index表(由index指向PCB),多个状态对应多个不同的状态index表(就绪索引表,阻塞索引表)。 5.进程的状态及其转换 (1) 核心态用户态 (2) 进程的三种基本状态 ①就绪态:进程已经具备运行条件,无CPU暂时不能运行。 ②执行态:进程占有了包括CPU在内的全部资源,并在CPU上运行。 ③等待态:进程因等待某种事件的发生而暂时不能运行的状态。 (3) 三种基本状态的转换 ①就绪->运行:调度程序选择一个新的进程运行。 ②运行->就绪:时间片用完;进程被中断(高优先级进程处于就绪状态)。 ③运行->等待:进程等待某一事件的发生。 ④等待->就绪:所等待的事件发生。 (4) 其它状态 ①创建状态:OS已完成为创建一进程所必要的工作,但还没有允许执行该进程。 ②终止状态:终止后进程移入该状态,不再有执行资格,表格和其它信息暂时保留。 ③挂起状态:把一个进程从内存转到外存。 (5) 挂起进程模型:由于进程优先级的引入,一些低优先级进程可能等待较长时间,从而被对换至外存。 ①就绪挂起状态:进程在外存,但只要进入内存,即可运行。 ②阻塞挂起状态:进程在外存并等待某事件的出现。 ③阻塞到阻塞挂起:没有进程处于就绪状态或就绪进程要求更多的内存资源。 ④就绪到就绪挂起:有高优先级阻塞进程和低优先级就绪进程时,系统会选择挂起低优先级就绪进程。 ⑤运行到就绪挂起:对抢先式分时系统,有高优先级阻塞挂起进程因事件出现而进入就绪挂起时,系统可能会把运行进程转到就绪挂起状态。 (6) 激活:把一个进程从外存转到内存。 ①就绪挂起到就绪:没有就绪进程或挂起就绪进程优先级高于就绪进程。 ②阻塞挂起到阻塞:一个进程释放足够内存时,系统会把一个高优先级阻塞挂起进程转为阻塞状态。
三、进程控制
1.进程控制的功能:完成进程创建与撤销、阻塞与唤醒、挂起与激活;完成进程状态的转换。 2.进程创建原语:为进程创建一个PCB,赋予一个统一进程标识符,为进程映像分配空间,初始化进程控制块,设置相应的链接(把新进程加入到就绪队列的链表中)。
Procedure Create(n, S0, P0, M0, R0)
Begin
i :=GetInternalName(n); //n为被创建进程的外部标识符
i.id := n; i.priority := P0; //初始化PCB,P0为进程优先级
i.CPU_State := S0; //S0为处理机的初始状态
i.Mainstore := M0; //M0为初始内存数
i.resources := R0; //R0为所需资源清单
i.status := Ready;
j := EP; i.parent := j; //插入家族队列
i.progeny := ∧; j.progeny := i;
i.sdata := RQ; insert( RQ, i ); //插入就绪队列,i.sdata是一个与进程状态有关的指针
End;
3.进程撤销原语:释放内外存空间,关闭所有打开文件,释放共享内存段和各种锁定的lock,撤销其子孙进程,释放PCB。 导致进程被撤销的原因: ①完成任务后正常终止。 ②由于错误导致非正常终止;祖先进程要求撤销某个子进程。
Procedure Destroy(n) //n为调用者提供的进程的外部标识
Begin
Sched := false;
i :=GetInternalName(n);
Kill(i);
if Sched then Scheduler else continue;
End;
Procedure Kill(i)
Begin
if i.status = “Running” then
stop(i); Sched := True; //如果进程正在运行,则立即停止运行,并设置调度标志为真
remove(i.sdata, i);
for all S∈i.progeny do Kill(S);
for all r∈Main store∪ i.resources do
Release(r);
Release (PCB(i))
End;(Kill是可递归的)
4.进程阻塞原语:保护中断现场,置进程的状态为“等待态”,将其插入该事件的等待队列WQ(r),转进程调度。 阻塞原因:进程期待的某事件尚未出现时,进程调用阻塞原语把自己阻塞起来。
Procedure block(r) //r为指向等待原因的对应等待队列的指针
Begin
i := EP; //从执行进程的指针获得进程的内部标识符i
stop(i); //停止进程i
i.status := “blocked”;
i.sdata := WQ(r);
insert(WQ(r), i);
scheduler; //进程调度程序
End;
5.进程唤醒原语 (1)唤醒原因:进程等待的事件发生,等待队列中的进程被唤醒。 (2)唤醒进程的2种方法: ①由系统进程唤醒(等待公共资源) ②由事件发生进程唤醒(等待私有资源)
Procedure wakeup(n)
Begin
i := GetInternalName(n);
remove( WQ(r), i ); //从相应的等待队列中摘下被唤醒的进程
i.status := “Ready”; //状态置为就绪态“Ready”
i.sdata := RQ;
insert( RQ, i); //插入就绪队列
continue; //唤醒进程返回或转进程调度
End;
6.挂起原语:将进程从活动就绪状态或阻塞状态变为相对静止的就绪挂起状态或阻塞挂起状态。 进程的挂起方式: ①发命令的进程自身挂起。 ②挂起具有指定标识符的进程。 ③将某进程及其全部或部分“子孙”进程挂起。
procedure Suspend(n, a) /* 挂起指定标识符n的 Begin 进程的进程原语*/
i := GetInternalName(n); /* 参数a是用于保存该 S := i.status; 进程PCB副本的内存区*/
if S=“Running” then stop(i);
a := copy PCB(i);
if S=“blockeda” then i.status := “blockeds”
else i.status := “readys”
if S= “Running” then Scheduler else continue;
End;
7.激活原语:使处于静止状态的进程变为活动状态。 激活方式: ①激活一个指定标识符的进程。 ②激活某进程及其所有“子孙”进程等。 ③当激活的进程处于“活动就绪”状态时,可能引起进程的重新调度。
procedure active(n) /*n为进程标志符*/
begin
i := GetInternalName(n);
i.status := if i.status=“readys” then “readya”
else “blockeda”;
if i.status = “readya” then scheduler;
else continue
End;
四、线程
1.引入线程的目的:减少程序在并发执行时所付出的时空开销,使OS具有更好的并发性。 ①进程可创建多个线程来执行同一程序的不同部分(相对独立的部分)。 ②所有线程可共享进程的主存,不需要特殊的通信机制。 2.线程的优点: (1) 减小并发执行的时间和空间开销,允许在系统中建立更多的线程来提高并发程度。 (2) 创建时间比进程短。(线程也要分时共享CPU) (3) 终止时间比进程短。 (4) 同进程内的线程切换时间比进程短。(上下文有许多是相同的) (5) 同进程内线程间共享进程的代码、数据、内存和文件资源,可直接进行不通过内核的通信;进程间的通信需要通过内核进行,以提供保护和通信所需机制。 (6) 一个进程的所有线程必须同时处于挂起状态;进程的终止会导致所有线程的终止。 3.线程的属性: (1) 轻型实体:一般不拥有系统资源,只有一点必不可少的、能保证其独立运行的资源。 (2) 独立调度和分派的基本单位。 (3) 可并发执行:不同进程的线程和同一进程中的线程。 (4) 共享进程资源:同一进程中的各线程可共享该进程所拥有的资源。 4.进程与线程的比较: (1) 调度 ①线程是调度、分派的基本单位。 ②同一进程中,线程的切换不会引起进程的切换;从一个进程中的线程切换到另一个进程中的线程时,将会引起进程的切换。 (2) 并发性 在引入线程的操作系统中,不仅进程之间可并发执行,在一个进程中的多个线程之间也可并发执行,使得操作系统具有更好的并发性,从而提高系统资源的利用率和系统吞吐量。 (3) 拥有资源 ①进程是系统中拥有资源的基本单位。 ②一般来说,线程不拥有系统资源(除少量必不可少的资源),但可以访问其隶属进程的资源。 (4) 系统开销 ①线程的创建、撤销、切换快,操作系统所付出的开销明显小于进程。 ②同进程内线程间共享进程的代码、数据、内存和文件资源,可直接进行不通过内核的通信;而进程间的通信需要通过内核进行,以提供保护和通信所需机制。 5.线程的实现方式 (1) 内核线程:线程在核心空间实现,核心知道线程存在,并对它们实施管理。 ①由内核的内部需求进行创建和撤销,用来执行一个指定的函数。 ②内核维护进程和线程的上下文信息。 ③线程切换由内核完成。 ④一个线程发起系统调用而阻塞,不会影响其他线程的运行。 ⑤时间片分配给线程,多线程的进程获得更多CPU时间。 (2) 用户线程:把线程库整个地放在用户空间,核心只对常规进程进行管理,并不知道线程是否存在。 ①不依赖于OS核心,维护由应用进程完成。 ②应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。 ③调度由应用软件内部进行,通常采用非抢先式和更简单的规则,也无需用户态/核心态切换,所以速度特别快。 ④一个线程发起系统调用而阻塞,则整个进程在等待。 ⑤时间片分配给进程,多线程则每个线程就慢。 (3) 轻权进程:内核支持的用户线程。一个进程可有一个或多个轻权进程,每个轻权进程支持一个或多个用户线程,并映射到一个内核线程。 (4) 混合线程
五、进程互斥和同步
1.进程间的关系 (1) 交互 ①互斥:多个进程不能同时使用同一个资源。 ②死锁:多个进程互不相让,都得不到足够的资源。 ③饥饿:一个进程一直得不到资源。 (2) 制约 ①间接制约:竞争,独占分配到的部分或全部资源,“互斥”。 ②直接制约:协作,等待来自其他进程的信息,“同步”。 2.互斥算法 (1) 临界区的访问过程 ①进入区:在进入临界区之前,检查可否进入临界区的一段代码。如果可以进入临界区,通常设置相应“正在访问临界区”标志。 ②临界区:进程中访问临界资源的一段代码。 ③退出区:将用于“正在访问临界区”标志清除。 ④剩余区:代码中的其余部分。 (2) 使用临界区应遵循的准则 ①有空让进:当无进程在互斥区时,任何有权使用互斥区的进程可进入。 ②无空等待:不允许两个以上的进程同时进入互斥区。 ③多中择一:当没有进程在临界区,而同时有多个进程要求进入临界区,只能让其中之一进入临界区,其他进程必须等待。 ④有限等待:任何进入互斥区的要求应在有限的时间内得到满足。 ⑤让权等待:处于等待状态的进程应放弃占用CPU。 ⑥平等竞争:任何进程无权停止其他进程的运行,进程之间相对运行速度无硬性规定。 (3) 进程互斥的软件方法 ①单标志:设立一个公用整型变量turn描述允许进入临界区的进程标识(在进入区循环检查是否允许本进程进入;在退出区修改允许进入进程标识)。 缺点:强制轮流进入临界区,没有考虑进程的实际需要。容易造成资源利用不充分。 ②双标志、先检查:设立一个标志数组flag[]描述进程是否在临界区,初值均为FALSE。在进入区检查另一个进程是否在临界区,不在时修改本进程在临界区的标志;在退出区修改本进程在临界区的标志。 优点:不用交替进入,可连续使用。 缺点:两个进程可能同时进入临界区,在检查对方flag之后和切换自己flag之前有一段时间,结果都检查通过(检查和修改操作不能连续进行)。 ③双标志、后检查:先修改后检查,可防止两个进程同时进入临界区。 缺点:两个进程可能都进不了临界区(在切换自己flag之后和检查对方flag之前有一段时间,结果都切换flag,都检查不通过)。 ④先修改、后检查、后修改者等待
(4) 进程互斥的硬件方法 ① Test-and-Set指令(TS指令):每个临界资源设置一个公共布尔变量lock,初值为FALSE。在进入区利用TS进行检查,有进程在临界区时,重复检查,直到其它进程退出时,检查通过。
boolean TS(boolean *lock) {
//lock表示资源的两种状态,初值为FALSE
boolean old;
old = *lock; *lock = TRUE;
return old;
}
lock (int *lock) //测试并加锁
{
while TS(&lock);
}
unlock (int *lock) //解锁
{
* lock = FALSE;
}
②Swap指令:每个临界资源设置一个公共布尔变量lock,初值为FALSE。每个进程设置一个私有布尔变量key。
void SWAP(int *a, int *b) {
int temp;
temp = *a; *a = *b; *b = temp;
}
key = TRUE;
do
{
SWAP(&lock, &key);
} while(key);
lock = FALSE;
③开关中断指令:进入临界区前执行“关中断”指令;离开临界区后执行“开中断”指令。 3.信号量 (1)每个信号量s除一个整数值s.count(计数),还有一个进程等待队列s.queue,是阻塞在该信号量的各个进程的标识。 (2)初始化指定一个非负整数值表示空闲资源总数。 ①若为非负值表示当前的空闲资源数。 ②若为负值其绝对值表示当前等待临界区的进程数。 (3)P原语:申请使用临界资源时调用
P(Semaphore s)
{
--s.count; //表示申请一个资源;
if (s.count <0) //表示没有空闲资源;
{
调用进程进入等待队列s.queue;
阻塞调用进程;
}
}
(4)V原语:唤醒进程等待队列中的头一个进程
V(Semaphore s )
{
++s.count; //表示释放一个资源;
if (s.count <= 0) //表示有进程处于阻塞状态;
{
从等待队列s.queue中取出一个进程P;
进程P进入就绪队列;
}
}
(5)利用信号量实现互斥:为临界资源设置一个互斥信号量mutex,初值为1,在每个进程中将临界区代码置于P(mutex)和V(mutex)原语之间。
const int n = 进程数;
Semaphore s = 1;
Void Process( int i) {
while ( true) {
P(s); // wait(s)
<critical section>
V(s) // signal(s)
remainder section
}
}
void main()
{
parbegin(Process(1),
Process(2),
...,
Process(n));
}
4.信号量集 (1)AND型信号量集:用于同时需要多种资源且每种占用一个时的信号量操作。将一段代码同时需要的多个临界资源,要么全部分配给它,要么一个都不分配。
Swait (S1,S2,…,Sn){
while (true){
if (S1>=1 && S2>=1 && … && Sn>=1){
for (i=1; i<=n; ++i) --Si;
break;
}
else{
调用进程进入第一个小于1信号量的等待队列Sj.queue;
阻塞调用进程;
}
}
}
Ssignal (S1,S2,…,Sn){
for (i=1; i<=n; ++i){
++Si;
for (each process P waiting in Si.queue){
从等待队列Sj.queue中取出进程P;
if (进程P通过Swait中的测试)
进程P进入就绪队列
else
进程P进入某等待队列;
}
}
}
(2)一般信号量集:用于同时需要多种资源、每种占用的数目不同、且可分配的资源还存在一个临界值时的处理。在AND型信号量集的基础上进行扩充,进程对信号量Si的测试值为ti,占用值为di。
Swait(s1,t1,d1;…;sn,tn,dn) (或SP)
If (s1>=t1 and s2>=t2 and … and sn>=tn) then
For i=1 to n do si:=si-di
Else 阻塞进程;
Ssignal(s1,d1;…;sn,dn) (或SV)
For i=1 to n do
Begin
si:=si+di; For all 被阻塞的Pi do 唤醒进程;
End;
5.利用信号量实现前趋关系(前趋图) (1)有向无循环图,用于描述进程之间执行的前后关系。 (2)每个结点表示一个进程、程序段或一条语句,结点间的有向边表示两结点间存在的偏序或前趋关系。 (3)前趋图中不能存在循环。 (4)若希望在S1执行后再执行S2,只需使进程P1和P2共享一个公用信号量S,并赋初值0。
Var a2,a3,a4,a5,a63,a64,a65 :=semaphore:=0,0,0,0,0,0,0;
Begin
Parbegin
Begin S1;V(a2);V(a3); End
Begin P(a2);S2;V(a4);V(a5); End
Begin P(a3);S3;V(a63); End
Begin P(a4);S4;V(a64); End
Begin P(a5);S5;V(a65); End
Begin P(a63); P(a64); P(a65); S6; End
Parend
End
6.管程:管程是关于共享资源的数据结构及一组针对该资源的操作过程所构成的软件模块。 (1)管程是管理进程间同步的机制,它保证进程互斥地访问共享变量,并方便地阻塞和唤醒进程。 (2)管程的特点: ①其内部的局部数据变量只能被管程内定义的过程所访问,不能为管程外声明的过程直接访问。 ②进程若想进入管程,必须调用管程内的某个过程。 ③一次只能有一个进程在管程内执行,其余调用该管程的过程均被挂起,等待该管程成为可用的。 ④管程能有效地实现互斥。 (3)管程的主要特征: ①模块化:一个管程是一个基本程序单位,可以单独编译。 ②抽象数据类型:管程是一种特殊的数据类型,其中不仅有数据,而且有对数据进行操作的代码。 ③信息掩藏:管程是半透明的,管程中的外部过程(函数)实现了某些功能,至于这些功能是怎样实现的,在其外部则是不可见的。 (4)条件变量: ①Wait(x):挂起等待条件x的调用进程,释放相应的管程,以便其它进程使用。 ②Signal(x):恢复执行先前因在条件x上执行wait而挂起的那个进程。 (5)管程的结构: ①入口等待队列:因为管程是互斥进入的,所以当一个进程试图进入一个已被占用的管程时它应当在管程的入口处等待,因而在管程的入口处应当有一个进程等待队列,称作入口等待队列。 ②紧急等待队列:如果进程P唤醒进程Q,则P等待Q继续,如果进程Q在执行又唤醒进程R,则Q等待R继续,…,如此,在管程内部,由于执行唤醒操作,可能会出现多个等待进程(已被唤醒,但由于管程的互斥进入而等待),因而还需要有一个进程等待队列,这个等待队列被称为紧急等待队列。它的优先级应当高于入口等待队列的优先级。
六、进程间通信
1.进程间通信的类型 (1)低级通信:只能传递状态和整数值(控制信息),包括进程互斥和同步所采用的信号量和管程机制。 (2)高级通信:能够传送任意数量的数据,包括:共享存储区、管道、消息等。 ①共享存储器系统:相互通信的进程共享某些数据结构或共享存储区。一组进程向该公共区中写,另一组进程从公共区中读。(基于共享数据结构的通信方式、基于共享存储区的通信方式) ②消息系统:进程间的信息交换以消息或报文为单位,程序员利用系统提供的一组通信命令(原语)实现通信。(直接通信方式、间接通信方式) ③利用共享文件的通信方式 2.消息缓冲 (1)原理 ①系统在操作系统空间设置一组缓冲区,其中每个BUFFER可以存放一个消息。 ②当发送进程需要发送消息时,执行send系统调用,操作系统为发送进程分配一个空缓冲区,并将所发送的消息从发送进程copy到缓冲区中,然后将该载有消息的缓冲区连接到接收进程的消息链链尾,如此就完成了发送过程。 ③在以后某个时刻,当接收进程执行到receive接收原语时,由操作系统将载有消息的缓冲区从消息链中取出,并把消息内容copy到接收进程空间,之后收回缓冲区,如此就完成了消息的接收。 (2)消息缓冲区结构
typedef struct message_buffer {
int size; //消息长度
char *text; //消息正文
int sendername; //发送者名字
ptrQueue next; //消息队列指针
}
(3)对PCB的扩充 ①Mutex:消息队列互斥操作信号量。 ②Sm:表示接收消息记数和同步信号量,表示消息队列中的消息数目。 ③Pm:消息队列首指针。 (4)发送和接收原语
Procedue send(receiver, a)
begin
getbuf(a.size, i); //申请缓冲区,i
i.sender := a.sender; // 将发送区中的信息
i.size := a.size; // 复制到消息缓冲区i中
i.text := a.text; i.next := 0;
getid(PCBSet, receiver, j); //获得接收进程的内部标识符
P(j.mutex);
insert(j.Pm, i); //将消息插入到接收者的消息队列
V(j.mutex); V(j.Sm);
End;
Procedure receive(b)
Begin
j := internal name; // 为接收者进程的内部标识
P(j.Sm);
P(j.mutex);
remove(j.Pm, i); // 将消息队列中的第一个消息移出
V(j.mutex);
b.sender : = i.sender; //将消息缓冲区 i 中的信息
b.size := i.size; //复制到接收区b
b.text := i.text;
End;
3.管道 (1)管道是一条在进程间以字节流方式传送的通信通道。 (2)由OS核心的缓冲区(通常几十KB)来实现,是的;常用于命令行所指定的输入输出重定向和管道命令。(先进先出的,一个进程写,一个进程读) (3)在使用管道前要建立相应的管道,然后才可使用。 4.消息 (1)通常是不定长数据块。消息的发送不需要接收方准备好,随时可发送。 (2)每个进程都有一个与之相关的消息队列,其功能类似于信箱。 (3)消息发送者指定发送的每个消息的类型,类型可以被接收者用作选择原则,接收者可以按先进先出的顺序接收信息,或者按类型接收。 5.套接字:双向的,数据格式为字节流(一对一)或报文(多对一,一对多);主要用于网络通信。
七、死锁问题
1.概述 (1)死锁的定义:一组进程中,每个进程都无限等待被该组进程中另一进程所占有的、因而永远无法得到的资源,这种现象称为进程死锁,这一组进程就称为死锁进程。 (2)死锁发生的原因: ①竞争资源:为多个进程所共享的资源不足,引起它们对资源的竞争而产生死锁。 ②并发执行的顺序不当:进程运行过程中,请求和释放资源的顺序不当,而导致进程死锁。 (3)死锁发生的条件: ①互斥:任一时刻只允许一个进程使用资源。 ②请求和保持:进程在请求其余资源时,不主动释放已经占用的资源。 ③非剥夺:进程已经占用的资源,不会被强制剥夺 ④环路等待:环路中的每一条边是进程在请求另一进程已经占有的资源。 2.死锁的预防:预防是采用某种策略,限制并发进程对资源的请求,使系统在任何时刻都不满足死锁的必要条件。 (1)预先静态分配法:(针对死锁的第2个条件)预先分配所需全部资源,保证不等待资源。 (2)有序资源使用法:(针对死锁的第4个条件)把资源分类按顺序排列,保证不形成环路。如果一个进程已经分配了R类型的资源,它接下来请求的资源只能是那些排在R类型之后的资源。 3.死锁的检测:允许死锁发生,操作系统不断监视系统进展情况,判断死锁是否发生。一旦死锁发生则采取专门的措施,解除死锁并以最小的代价恢复操作系统运行。 (1)资源分配图: 如果资源分配图中没有环路,系统不会陷入死锁状态;如果存在环路,那么系统可能出现死锁,但不确定。关键是:出现环路后,是否还有进程能够继续前进。 (2)死锁定理:S