简介:这份资料是面向山东大学操作系统课程期末复习的笔记型PDF,适合正在备考操作系统、需要系统梳理知识框架的本科生使用。内容围绕操作系统基本概念与功能展开,涵盖进程管理、存储管理、文件管理、设备管理、作业管理与文件系统管理等核心章节,并重点整理了进程与程序的区别、进程三态转换时机、PCB组成、父子进程与僵尸/孤儿进程、进程调度队列、进程间通信的消息传递与共享内存对比,以及Simple structure、Layered、Microkernel三种结构设计的优劣。资源包内共1个PDF文件,压缩包约2.91MB,篇幅紧凑,便于打印或平板翻阅。目前已有974人学习下载,说明其内容与考试重点贴合度较高。读者可借助这份笔记快速定位高频考点,配合教材完成概念辨析与状态转换图的记忆,适合作为期末冲刺阶段的查漏补缺材料。
1. 期末操作系统复习笔记:一份能直接进考场的知识压缩包
如果你正在搜“期末 操作系统 山东大学”,大概率是离考试没几天了,手里课件、教材、PPT 堆了一桌,却不知道从哪一页开始翻。这份复习笔记就是为这个场景准备的:它不是教材的替代品,而是一份把操作系统核心考点按章节压缩好的知识清单,覆盖导论、系统结构、进程、线程、CPU 调度、进程同步、死锁、内存管理、虚拟内存、文件系统接口与实现。适合两类人:一是想快速建立框架、把零散概念串起来的同学;二是已经看过一遍书、需要拿一份高密度材料做最后排查的人。笔记里既有概念定义,也有状态转换、调度算法、银行家算法、页面置换这类计算题的判断依据,能直接当复习提纲用。
2. 进程与线程:状态转换、PCB 和调度队列怎么串起来
2.1 进程不是程序,PCB 才是管理入口
进程是某一特定功能的程序的一次执行过程,是操作系统中最基本的单位。程序是存储在磁盘上的静态实体,当可执行文件加载到内存中时,程序成为进程。这个区别在选择题和简答题里反复出现,判断标准就一条:静态还是动态、有没有生命周期、一个程序能不能对应多个进程。
进程的组成要记三要素:程序、数据、PCB。代码段、数据段、寄存器、栈、堆是进程运行时的组成部分,但操作系统管理进程靠的是 PCB。PCB 记录进程的外部特征,描述进程的运动变化过程。进程被选中执行后可能发生三类事情:发出 I/O 请求进入 I/O 队列;创建子进程并等待其结束;被中断强制释放 CPU 回到就绪队列。
父子进程的关系是代码题常客。子进程 pid=0,父进程 pid>0。写时复制让父子进程各自变量互不影响。终止路径要分清:子进程 exit() 后,父进程通过 wait() 拿到终止子进程的标识符;父进程先终止,子进程可能变成孤儿进程,Linux 和 Unix 会把 init 作为其父;子进程终止但父进程没调用 wait,子进程变成僵尸进程。
2.2 三种队列和三级调度程序
进程进入系统后加入作业队列,所有进程都在这个序列里。就绪队列存放主存中已就绪准备执行的进程,通常由链表实现。设备队列存放等待 I/O 设备的进程。这三个队列是理解调度程序分工的基础。
长期调度程序从缓冲池中选择进程装入内存,准备执行,控制多道程序度。短期调度程序从准备执行的进程里选择进程并分配 CPU,频率最高。中期调度程序能把进程从内存换出挂起,暂存磁盘,之后再换入。I/O bound 和 CPU-bound 的区分会影响长期调度的选择。
进程间通信两种方式要能对比。共享内存由应用程序员提供通信,操作系统提供共享内存区域,建立后不需要内核帮助,速度快,但访问和操作代码要自己写,POSIX 是典型实例。消息传递由操作系统提供机制,适合交换较少数据,更容易实现,Mach 是实例。客户机服务器系统通信还有套接字、远程过程调用、管道、远程方法调用。
线程部分抓住引入理由:响应度高、资源共享、经济、多处理器体系结构利用。用户线程由库管理,不支持抢占式调度;内核线程由操作系统直接支持和管理,阻塞不相互影响,切换代价接近进程。多线程模型有多对一、一对一、多对多。线程取消分异步撤销和延迟撤销,线程池预先创建线程等待工作。
提示:进程状态转换图要能默画。运行到等待是等待某事件发生;等待到就绪是事件发生了;运行到就绪是时间片到或有更高优先级进程出现;就绪到运行是被调度程序选中。
3. CPU 调度与同步:从 FCFS 到信号量的计算题拆解
3.1 调度算法判断标准和计算套路
分派程序把 CPU 控制交给短期调度程序选择的进程,功能包括切换上下文、切换到用户模式、跳转到用户程序合适位置。分派延迟是停止一个进程启动另一个的时间。非抢占式调度一旦运行就持续到自身原因结束,抢占式允许更高优先级进程剥夺 CPU。
FCFS 先到先服务,非抢占,存在护航效果,若干短进程被迫跟在长进程后。SJF 最短作业优先,具有最小等待时间,常用于长期调度,分非抢占和抢占两种,抢占版叫 SRTN。HRRN 最高响应比优先。优先级调度可抢占也可非抢占,注意不同系统数字大小与优先级高低的关系。饥饿是低优先级进程永远不被执行,老化是逐渐增加等待很长时间的进程的优先级。
RR 轮转法为分时系统设计,每个进程执行一个时间片后进入就绪队列末尾,是抢占式。时间片 q 太大退化成 FCFS,太小导致上下文切换开销过大,希望时间片比上下文切换时间长。多级队列调度把就绪队列分为多个独立队列,按进程属性分配,每个队列有自己的调度方法,队列间一般采用固定优先级抢占调度。多级反馈队列允许进程在队列间移动,占 CPU 时间过多会被挪到更低优先级队列,等待时间过长会被挪到更高优先级队列,I/O 约束和交互进程留在更高优先级队列,是最常用且最复杂的调度程序。
衡量指标包括 CPU 使用率、吞吐量、周转时间、等待时间、响应时间。需要使 CPU 使用率和吞吐量最大化,使周转时间、等待时间、响应时间最小化,尽量优化平均值。交互系统里最小化响应时间的方差比最小化平均响应时间更重要。
3.2 临界区三条件和信号量写法
临界区是每个进程中可能改变共同变量、更新表、写文件的代码段,没有两个进程可以同时在临界区内执行。解决方案要满足三个条件:互斥、有空让进、有限等待。Peterson 算法用于两个进程在临界区和剩余区交替执行,是软件方法。硬件同步用锁防护临界区,TestAndSet 是原子指令。
信号量 S 是整数变量,除初始化外只能通过 P 和 V 操作访问。计数信号量值域不受限制,二进制信号量只能为 0 或 1,也叫互斥锁。自旋锁在代码中连续循环忙等待。解决忙等待的办法是让每个信号量有一个整型值和一个进程链表,P 操作中信号量不为正时阻塞自己并加入链表,V 操作从等待链表取一个唤醒。
读者/写者问题要求写者对数据库有排他访问。生产者/消费者问题中,生产者把产品放入具有 n 个缓冲区的缓冲池,消费者从缓冲区取走产品。信号量用于同步,互斥锁用于互斥;互斥锁只能为 0 或 1,信号量可以为其他整数;互斥锁加锁和解锁由同一线程使用,信号量可以一个进程释放另一个线程得到。
自旋锁在单处理器系统中不能存在,因为只有一个处理器为多个进程共享,忙等待浪费 CPU 时钟。多处理器系统中一个线程在一个处理器自旋时,另一线程可在另一处理器上进入临界区执行。
// 生产者-消费者信号量伪代码框架 semaphore mutex = 1; // 保护缓冲池的互斥锁 semaphore empty = n; // 空缓冲区数量 semaphore full = 0; // 满缓冲区数量 producer() { while (true) { produce_item(); P(empty); // 等待空位,empty 减 1 P(mutex); // 进入临界区 insert_item(); V(mutex); // 离开临界区 V(full); // 满位加 1,唤醒消费者 } } consumer() { while (true) { P(full); // 等待产品,full 减 1 P(mutex); remove_item(); V(mutex); V(empty); // 空位加 1,唤醒生产者 consume_item(); } }P 操作申请资源,信号量减 1,小于 0 时阻塞;V 操作释放资源,信号量加 1,小于等于 0 时唤醒等待进程。mutex 保证缓冲池操作的互斥,empty 和 full 控制生产者和消费者的推进节奏。考试写代码时先声明信号量初值,再写两个进程的循环体,P 和 V 的顺序不能颠倒,否则可能死锁。
4. 死锁与内存管理:银行家算法和分页地址映射的避坑清单
4.1 死锁四个必要条件和处理策略
死锁是一组进程,每个进程都持有一定资源,并向系统申请其他进程当前拥有的资源,进入死循环,每个进程都无法推进。四个必要条件:互斥、占有并等待、非抢占、循环等待。资源分配图中,申请边是 P 申请资源类型 R 的一个实例,分配边代表 R 的一个实例已分配给 P。没有环则无死锁;有环且每个资源只有一实例则存在死锁;一个资源有若干实例时可能有死锁。
死锁处理分三类:死锁预防、死锁避免、允许进入死锁后进行检测和恢复,以及忽视死锁问题。死锁预防是静态策略,限制申请资源,确保至少一个必要条件不成立。方法包括进程执行前申请并获得所有需要的资源、申请其他资源前释放已分配资源、把非抢占变为抢占、对所有资源类型完全排序要求按递增顺序申请。
死锁避免是动态策略,操作系统事先得到进程申请和使用资源的额外信息,跟踪并评估资源分配过程。安全状态存在安全序列,安全状态不会死锁,不安全状态可能死锁,要确保系统永远不会进入不安全状态。资源分配图用于每个资源只有一个实例的情况,需求边用虚线表示,只有在申请边变成分配边而不会形成环时才允许申请。银行家算法用于每个资源有多个实例的情况,新进程进入系统时必须说明每种资源可能的最大需求数量,申请资源时系统计算分配后是否仍处于安全状态。
死锁检测中,单个实例用等待图,有环存在死锁;多个实例用类似银行家算法的检测算法,找 request 小于 available 加前一个 allocation 的进程序列,排不进序列的产生死锁。死锁恢复选择一个牺牲品进程,回滚或终止进程并重启。饥饿是某进程总被选为牺牲品。
死锁和饥饿的异同要能写:相同点是都由于竞争资源引起;不同点是死锁进程都处于等待状态,饥饿可能出现在忙等待的进程;死锁等待永远不会被释放的资源,饥饿等待会被释放但不会分配给自己的资源;死锁一定发生循环等待,饥饿则不然;死锁涉及多个进程,饥饿可能只有一个;饥饿情形下至少有一个进程能正常运行,死锁可能使整个系统崩溃。
4.2 分页、分段和地址映射的常见翻车点
内存管理机制包括固定分区、可变分区、分页、分段、段页式。连续空间分配中,固定分区把用户空间划分为固定大小分区,每个分区只装入一个进程。可变分区不预先划分,根据进程大小动态建立分区,连续可用内存空间称为孔。首次适应分配第一个够大的孔,最佳适应分配足够大的孔里最小的,最差适应分配所用孔里最大的。外碎片是可用内存总和满足请求但不连续,用紧缩解决;内碎片是分配进程后在分区内被浪费的内存。
分页把用户进程空间分为相同大小的页,物理内存分成相对应的帧。页表基寄存器 PTBR 存放页表的最小物理地址,页表长度寄存器 PTLR 存放页表大小。TLB 是快表,只存放页表的一部分,查找时并行搜索。二级页表要访问三次内存:两次页表一次主存。Valid 表示在逻辑地址内的页,invalid 表示不在逻辑地址内的页。共享页中共享代码是可重入的,可重入代码不能自我修改,每个进程有各自的寄存器副本和数据存储。
分段按程序自身逻辑划分若干程序段,每段有段号,内存空间动态划分为长度不相同的区域,以段为单位分配,每段在内存中占连续空间,各段之间可不相邻。CPU 取到逻辑地址后,用段号查段表得到该段在内存的起始地址,与段内偏移量计算出物理地址。
地址绑定分编译时、加载时、执行时。编译时知道进程将在内存中的驻留地址,生成绝对代码;加载时编译器生成重定位代码;执行时绑定延迟到执行中进行,需要特定硬件。逻辑地址是 CPU 生成的地址,物理地址是内存单元能看到的地址。编译和加载时生成相同的逻辑地址和物理地址,运行时地址绑定方案会导致两者不同。
注意:分页和分段比较是高频简答题。分页对用户透明,页大小固定,会产生内碎片;分段对用户可见,段大小可变,会产生外碎片。段页式先分段再分页,兼顾逻辑结构和内存利用率。
5. 虚拟内存与文件系统:页面置换和 FCB 查找的实战排查
5.1 页面置换算法选择与颠簸判断
虚拟内存将用户逻辑内存和物理内存分开,好处包括弥补物理内存不足、提高反应速度、减少对物理内存的读取、允许文件和内存通过共享页为多个进程共享。按需调页只有程序执行需要时才载入页,从未访问的页不会调入物理内存。页错误陷阱是访问尚未调入内存的页,缺页率等于缺页次数除以访问页面总数。处理缺页包括处理页错误中断、读入页、重新启动进程。写时复制让父子进程开始时共享同一页面,任何一个进程要写就创建副本。Vfork 不使用写时复制,将父进程挂起,子进程使用父进程的地址空间。
页面置换算法要能对比。FIFO 替换最先调入的页。最优置换算法替换未来访问页中最远的,只能用于和其他方法作比较。LRU 替换最近最少使用的页,计数器实现把时钟值复制进计数器,替换计数值最小的,需要遍历整个表格;栈实现引用某页时把它移到栈顶,栈底为牺牲页。二次机会算法引用位初始化为 1,用 FIFO 选择某页面,访问位为 0 则置换,为 1 则挪到链表尾并把访问位改成 0。时钟算法用指针指向置换页面的下一个页面。增强二次机会算法首选最近没使用没修改过的页面,使用位权重高于修改位。LFU 置换计数最小的页,MFU 置换计数最大的页,基于计数器的算法实现费时,不常用。
帧分配分平均分配和比例分配。全局置换从所有帧中选择一个置换,系统吞吐量更好,常用;局部置换每个进程仅从自己分配到的帧里选择,有的帧会一直空闲。系统颠簸是频繁的调页行为,若一个进程换页时间大于运行时间,这个进程就是颠簸的。页错误率策略是页错误率低则减少分配帧数,页错误率高则增加分配帧数。内存映射文件可以把一个磁盘块映射成内存的一页。
5.2 文件系统实现与 FCB 查找路径
文件系统接口部分,基于目录管理的文件系统中实现文件共享的方法包括无环图目录结构,同一文件或子目录出现在两个不同目录中可以实现共享文件。对于符号链接,可以不处理其他悬挂链接;对于非符号链接,文档可以增加引用计数字段以避免悬空指针。
文件系统实现中,引导控制块包括系统从该卷引导 OS 所需要的信息,卷控制块包括卷的详细信息,文件控制块 FCB 包含各项有关文件信息、访问许可、文件大小等。系统范围内打开的文件表包含每个打开文件的 FCB 副本及其他信息,单个进程的打开文件表包含指向系统范围内已打开文件表中相关条目的指针。
文件系统依据用户给出的文件名找到 FCB 的路径要能复述:系统先调用 open(),会搜索系统文件表看该文件是否已被其他进程使用,若是就在单个进程文件表中创建一项指向系统文件表;将文件名传给文件系统,在打开文件时根据给定文件名搜索目录结构,找到文件后其 FCB 复制到系统范围内的打开文件表;接着在单个进程文件表中增加一个条目,通过指针将系统文件表的条目和其他域相连;open() 返回一个指向单个进程的文件打开表中合适条目的指针。
虚拟文件系统在文件系统接口和某个具体的本地文件系统实现或远程文件系统实现之间增加虚拟文件系统层,把不同实现的文件系统统一起来。文件分配空间有三种方式:连续分配每个文件占一系列连续磁盘块,FCB 中存储首块地址,访问性能最好,简单,但存在外部碎片,文件长度变大困难;链接分配 FCB 中存储文件首块地址,每个文件的数据块是单向链表结构,文件目录中包含指向第一块和最后一块的指针,数据块内除数据外还包含指向下一块的指针,无外部碎片,但指针损坏会导致严重可靠性问题,不能有效支持直接访问;FAT 文件分配表把散落的指针收拢,下标是块号,值指向连接中的下一个块号,便于快速访问和高速缓存,提高随机访问性能,新块分配也更简单,FAT32 每项在表内占 32 位即 4 字节。
# 查看文件系统类型和挂载信息,辅助理解文件系统实现 df -T # 输出示例: # Filesystem Type 1K-blocks Used Available Use% Mounted on # /dev/sda1 ext4 51474912 8234560 40620352 17% / # 查看 inode 信息,对应 FCB 中的元数据部分 stat /etc/passwd # 输出包含 inode 号、大小、权限、时间戳等,对应 FCB 中的访问许可和文件大小 # 查看打开文件表相关限制 ulimit -n # 输出当前进程可打开的最大文件描述符数量df -T 显示文件系统类型和挂载点,帮助理解不同文件系统实现的差异。stat 输出 inode 号、文件大小、权限、时间戳,对应 FCB 中记录的文件信息。ulimit -n 查看进程可打开文件描述符上限,对应单个进程打开文件表的容量限制。排查文件系统问题时,先确认文件系统类型,再看 inode 是否耗尽,最后检查打开文件表是否达到上限。
6. 考前最后一遍:用错题反推知识盲区
复习到最后一两天,最有效的做法不是从头翻笔记,而是拿一套真题或课后题,按章节标记错题,再回到笔记里定位对应知识点。我自己的习惯是准备一张 A4 纸,左边写错题编号,右边写它考的是哪个概念、哪个算法、哪个条件。比如银行家算法算错,往往不是计算问题,而是安全序列的判断条件没记牢:进程仍可以申请的资源数小于当前可用资源加所有它前面的进程所占用的资源。页面置换算错,多半是没分清 FIFO、LRU 和时钟算法的指针移动规则。
下面这张表可以用来做最后一轮自查,每个条目能口述出关键判断标准就算过。
| 知识块 | 自查问题 | 判断标准 |
|---|---|---|
| 进程与线程 | 进程和程序区别 | 静态/动态、生命周期、一对多 |
| 进程状态 | 四种转换时机 | 运行-等待、等待-就绪、运行-就绪、就绪-运行 |
| CPU 调度 | RR 时间片影响 | q 大退化为 FCFS,q 小切换开销大 |
| 同步 | 临界区三条件 | 互斥、有空让进、有限等待 |
| 死锁 | 四个必要条件 | 互斥、占有并等待、非抢占、循环等待 |
| 死锁避免 | 安全状态判断 | 存在安全序列,不安全可能死锁 |
| 内存管理 | 分页分段区别 | 页固定透明有内碎片,段可变可见有外碎片 |
| 虚拟内存 | 页面置换算法 | FIFO、LRU、时钟、增强二次机会 |
| 文件系统 | FCB 查找路径 | open 搜索系统文件表,复制 FCB,返回指针 |
最后一晚不要再开新题,把错题对应的概念在笔记里找到原文,读两遍,合上笔记用自己的话复述一遍。复述卡住的地方就是第二天早上进考场前最后要看的内容。从那以后我每次带人复习操作系统,都强制走一遍“错题定位到笔记原文”的流程,比盲目刷题有效得多。希望帮到你。
本文还有配套的精品资源,点击获取