一、操作系统的作用
操作系统通过管理计算机的软硬件资源,提升系统的整体运行效率。同时,它还改善了人机交互体验,为用户提供了更加友好和便捷的操作环境。
二、进程管理
进程是程序在特定数据集合上的一次执行过程,是系统进行资源分配与调度的基本单位。一个完整的进程通常由三部分构成:程序块、数据块以及进程控制块(PCB)。
■ 进程与程序的区别
程序是一组为实现特定功能而编写的指令集合,具有静态性,只要未被删除就永久存在;而进程则是程序的一次动态执行过程,具有生命周期——从创建开始,到任务完成被撤销而结束。没有程序就没有进程。此外,进程是系统中资源分配和调度的独立单元,程序本身不具备这一特性。
■ 三态模型
■ 五态模型
■ 同步与互斥
同步指的是多个合作进程之间存在的直接制约关系;互斥则体现为多个进程对临界资源的竞争所导致的间接制约。
临界资源:指在同一时刻只能被一个进程访问的资源,例如打印机或磁带机。
临界区:进程中用于操作临界资源的代码段。
信号量:一种特殊的变量,用于协调进程间的同步与互斥操作。
■ 进程管理-PV操作
PV操作是实现进程间同步和互斥的重要机制,基于不可分割的原语操作。原语是由多条机器指令组成的程序段,在执行过程中不能被中断,即具备原子性。
信号量S的含义如下:
当 S ≥ 0 时,表示当前可用资源的数量;
当 S < 0 时,其绝对值代表等待该资源的进程数量。
P操作(申请资源):
将S减1(S := S - 1)。若结果 S ≥ 0,则进程继续运行;否则(S < 0),该进程进入阻塞状态,并插入阻塞队列。
V操作(释放资源):
将S加1(S := S + 1)。若结果 S > 0,则当前进程继续执行;若 S ≤ 0,则从阻塞队列中唤醒一个进程并将其加入就绪队列,之后当前进程继续运行。
■ PV与前趋图结合
通过将PV操作应用于前趋图中的节点,可以有效描述进程之间的执行顺序依赖关系,确保各步骤按预定逻辑执行。
■ 死锁
死锁是指两个或多个进程因相互等待对方持有的资源而造成的所有相关进程都无法继续推进的现象。一旦某个进程陷入等待不可能发生的事件,即形成死锁。若多个进程陷入此类循环等待,可能导致整个系统停滞。
产生死锁的四个必要条件包括:
1. 互斥条件
2. 保持和等待条件
3. 不可剥夺条件
4. 环路等待条件
预防死锁的方法是破坏上述任一条件;避免死锁可通过有序资源分配法或采用银行家算法实现。
保证系统不发生死锁所需的最小资源数需满足以下两点:
(1)每个进程均获得其最大需求量减一的资源;
(2)在此基础上,系统仍至少剩余一个可用资源。
■ 银行家算法
该算法的核心在于安全地分配资源,具体原则如下:
- 只接纳那些最大资源需求不超过系统总资源量的进程;
- 允许进程分阶段请求资源,但累计请求总量不得超过其声明的最大需求;
- 若当前资源不足以满足某进程尚需的资源,则可延迟分配,但必须确保该进程最终能在有限时间内获取所需资源,从而完成执行。
■ 任务的调度
操作系统通过调度程序来实现任务调度功能。调度程序以函数形式存在于内核中,可在不同模块中被调用,负责从就绪队列中选择下一个要执行的任务。它本质上不是独立任务,而是CPU资源的管理者。
调度算法是指调度程序在决策过程中遵循的一组规则,用以确定特定时刻应运行哪一个任务。
● 调度的方式
1. 不可抢占调度方式(Non-Preemptive)
一旦任务被选中运行,就会持续执行,直到因I/O操作、主动让出CPU或其他阻塞原因而停止。
2. 可抢占调度方式(Preemptive)
允许调度程序在任务运行期间强行中断其执行,并切换至其他更高优先级或更紧急的任务。
▲ 任务的调度 - FCFS
先来先服务(First-Come, First-Served, FCFS)是一种简单的调度策略,按照任务到达就绪队列的先后顺序进行调度。
▲ 任务的调度 - SJF
最短作业优先(Shortest Job First, SJF)算法优先调度预计运行时间最短的任务,有助于减少平均等待时间。
▲ 任务的调度 - RR
时间片轮转(Round Robin, RR)算法为每个任务分配固定长度的时间片,当时间片耗尽时即发生调度,适用于分时系统。
▲ 任务的调度 - 优先级算法
根据任务设定的优先级进行调度,高优先级任务优先获得CPU资源。
● 优先级算法 - 优先级分组
将任务划分为若干优先级组,组内再按一定策略调度,兼顾响应速度与公平性。
● 优先级算法 - 优先级反转
当低优先级任务持有高优先级任务所需的资源时,可能出现优先级反转现象,可通过优先级继承或天花板协议加以解决。
▲ 实时系统调度
实时系统要求任务在严格时限内完成,常用调度方法包括最早截止时间优先(EDF)和速率单调调度(RMS)等。
■ 任务间通信
进程之间需要通过一定的机制交换信息,常见的通信方式包括共享内存、消息传递、管道、信号量等,保障并发执行的协调性和数据一致性。
(First Come First Served,FCFS),又称先进先出调度算法(First In First Out,FIFO),是一种按照任务到达时间的先后顺序进行调度的策略。该算法属于不可抢占类型,即一旦某个任务占用CPU开始执行,就必须等到它运行结束或主动阻塞后才能释放处理器资源。当被阻塞的任务重新唤醒时,会被插入就绪队列的尾部,继续等待下一轮调度。
FCFS算法的主要特点是实现简单、逻辑清晰、易于理解和编程实现。然而,其调度性能受任务到达顺序影响较大。若短执行时间的任务排在长任务之后,则会导致平均周转时间显著增加,从而降低系统整体效率。

短作业优先调度算法(Shortest Job First,SJF)则在任务执行前预估其所需运行时间,并优先调度预计执行时间较短的任务。这种策略有助于减少平均等待时间和提高系统吞吐量。SJF算法存在两种实现方式:一种为不可抢占模式,即任务一旦开始执行便不会被中断;另一种为可抢占模式,也称为最短剩余时间优先(SRTF),允许更高优先级(更短执行时间)的新任务抢占当前正在运行的任务。
时间片轮转调度(Round-Robin Scheduling,RR)将所有就绪任务按到达顺序组成一个循环队列,调度器每次从队首选取一个任务分配一个固定时间段——即“时间片”——供其使用CPU。若任务在时间片内完成或因I/O等操作而阻塞,则立即让出处理器;否则,当时间片耗尽时,该任务被移至就绪队列末尾,下一个任务获得执行机会。
时间片轮转法的优点在于保证了良好的公平性和活动性,使得每个任务都能定期获得CPU时间,避免个别任务长期独占资源。但时间片大小的选择至关重要:若时间片过大,RR退化为类似FCFS的行为,失去轮转意义;若时间片过小,则频繁的任务切换会带来较大的系统开销,降低实际用于应用处理的有效时间比例。
优先级调度算法突破了默认所有任务同等重要的假设,为每个任务赋予一个优先级,在调度时选择当前就绪队列中优先级最高的任务执行。根据是否支持抢占,可分为可抢占式与不可抢占式两种。前者允许高优先级任务随时中断低优先级任务的执行,后者则需等待当前任务自愿放弃CPU后再进行调度决策。
任务优先级可通过静态或动态方式设定。静态优先级在任务创建时确定并保持不变直至终止,虽然管理简便,但可能导致低优先级任务长时间无法获得执行机会,出现“饥饿”现象。动态优先级则允许在任务运行过程中依据系统状态(如等待时间、资源需求等)调整其优先级,以提升调度灵活性和系统响应能力。
● 优先级分组机制结合了优先级调度与时间片轮转的思想:不同优先级组之间采用优先级算法决定执行顺序,而在同一组内的多个任务之间则采用RR策略共享CPU时间,既保障了高优先级任务的及时响应,又兼顾了同级别任务间的公平性。
● 优先级反转是指高优先级任务因依赖低优先级任务持有的资源而被迫等待,而此时低优先级任务又被中等优先级任务所阻塞的情况。这种现象可能引发严重的实时性问题,通常通过优先级继承或优先级天花板等协议加以解决。
在实时系统中,常用的调度算法包括:
(1)单调速率调度算法(Rate Monotonic Scheduling, RMS):一种静态优先级分配方法,适用于周期性任务。其核心原则是任务周期越短,赋予的优先级越高;周期越长,优先级越低。RMS假设任务相互独立、可被抢占,且执行时间恒定,是一种理想化的模型。尽管现实中任务常需通信与同步,导致难以完全满足前提条件,但RMS仍被广泛用作理论分析和初步设计的基础。
(2)最早期限优先调度算法(Earliest Deadline First, EDF):一种动态优先级调度机制,根据各任务的截止时间来动态调整优先级。距离截止时间最近的任务获得最高优先级。每当有新任务进入就绪状态或已有任务接近时限时,系统都会重新评估并调整调度顺序,确保关键任务得以按时完成。EDF具有较高的资源利用率和较强的适应能力,被认为是目前性能较优的实时调度方案之一。
■ 任务间通信(Intertask Communication)指多个任务为协同工作而交换数据和控制信息的过程。根据传输能力和复杂度,可分为两类:
低级通信:主要用于传递简单的控制信号或状态标志,如使用信号量实现互斥与同步,或通过异步信号通知事件发生。
高级通信:支持大量数据的传输,主要包括三种形式:共享内存、消息传递和管道。
① 共享内存(Shared Memory):多个任务共同访问同一段物理或虚拟地址空间,将其作为公共数据缓冲区,可自由读写任意类型的数据结构。该方式传输效率高,但必须配合互斥机制(如互斥锁、信号量)防止竞争条件,确保数据一致性。因此,共享内存通常需要额外的同步手段来协调访问行为。
消息(Message):指一段长度可变的内存缓冲区,内容由用户自定义,可以包含实际数据、指向数据块的指针,或者为空。消息传递机制允许任务间通过发送和接收消息实现解耦通信,常用于分布式或模块化系统中。
消息的解释工作由应用程序负责完成。从操作系统的角度来看,消息本身没有固定的格式,所有消息均被视为字节流,不具有特定语义。而从应用的角度出发,消息会依据其自定义的格式被解析为具体含义。在某些情况下,应用可能仅将消息作为状态标志使用,此时消息机制主要用于实现任务间的同步操作。
② 消息传递
任务之间通过发送和接收消息的方式进行信息交换,这种通信方式称为消息传递。操作系统负责维护整个消息机制,包括设定寻址方式、认证协议以及管理消息数量等参数。
该机制通常提供两个基本操作:
- send操作:用于发送一条消息;
- receive操作:用于接收一条消息。
任务间的消息通信可分为以下两种模式:
直接通信:通信双方必须明确指定对方的身份(即命名)。例如,Send(P, message) 表示向任务 P 发送消息;Receive(Q, message) 表示从任务 Q 接收消息。
间接通信:通信双方无需直接指明消息的来源或目标,而是通过一个中间媒介进行消息传递。
一些操作系统内核进一步将消息机制细分为两类:邮箱和消息队列。
邮箱:只能存储单条消息,适用于低开销的信息传输场景。每个邮箱可保存一条固定大小的字节消息。
消息队列:能够容纳多条消息,为任务间提供带缓冲能力的通信方式,属于间接通信的一种实现形式。
③ 管道(pipe)
管道是一种内核对象,用于实现任务之间的非结构化数据交换及同步控制。传统实现中,管道是单向的数据传输通道。其中的数据以非结构化的字节流形式存在,并按照先进先出(FIFO)的顺序被读取。
当管道为空时,读操作会被阻塞;当管道满时,写操作也会被阻塞。
管道与消息队列的主要区别在于:
- 管道并不区分多条独立消息,其所存储的是连续的非结构化字节流;
- 管道中的数据严格遵循先进先出原则;
- 管道支持 select 操作,可用于多路I/O监控,而消息队列一般不支持此功能。
以上内容即为本文的全部介绍。