一、操作系统基础:功能、特征与分类
操作系统(OS)是硬件与应用的“中间层”,需明确核心功能、运行特征、分类方式与内核态/用户态机制。
1.1 操作系统核心功能
OS 围绕“资源管理+用户接口”设计,覆盖五大核心功能:
功能模块 | 核心职责 | 典型技术实现 |
---|---|---|
进程管理 | 进程调度、同步、通信、死锁处理 | 时间片轮转、PV操作、银行家算法 |
内存管理 | 内存分配、回收、虚拟内存管理 | 分页/分段、LRU页面置换 |
文件管理 | 文件存储、组织、访问控制 | 索引文件、空闲块链表 |
设备管理 | 设备分配、I/O控制、缓冲管理 | DMA、SPOOLing技术 |
用户接口 | 命令行、图形界面、系统调用 | shell、API封装 |
1.2 操作系统特征
OS 具备并发、共享、虚拟、异步四大特征,是区分普通软件的核心标志:
特征 | 定义与表现 | 示例说明 |
---|---|---|
并发(Concurrency) | 多任务“宏观并行、微观串行”执行 | CPU 分时调度多个进程 |
共享(Sharing) | 资源被多个进程共同使用 | 内存共享、打印机共享 |
虚拟(Virtual) | 硬件资源的逻辑抽象 | 虚拟内存(磁盘→内存)、虚拟设备(SPOOLing) |
异步(Asynchronism) | 进程执行“走走停停”,结果不可再现 | 进程因I/O阻塞后重新调度 |
1.3 操作系统分类
OS 按用户规模、处理方式、体系结构分为多类,典型系统如下:
分类维度 | 类型 | 代表系统 | 核心特点 |
---|---|---|---|
用户规模 | 单用户系统 | MS - DOS | 同一时间仅一个用户使用 |
多用户系统 | Linux、UNIX | 支持多用户同时登录 | |
处理方式 | 批处理系统 | 早期大型机批处理系统 | 成批处理作业,减少人工干预 |
分时系统 | Linux、UNIX | 时间片轮转,多用户交互响应 | |
实时系统 | VxWorks、QNX | 强时效性,保障关键任务执行 | |
体系结构 | 单机OS | Windows、macOS | 单硬件节点运行 |
分布式OS | Amoeba、Mach | 多节点协同,透明共享资源 |
1.4 内核态与用户态:运行机制
OS 通过特权级划分保障系统安全,核心机制:
- 内核态(Kernel Mode):执行特权指令(如内存分配、I/O操作),访问所有资源;
- 用户态(User Mode):执行普通指令,仅访问用户空间资源;
- 状态切换:用户程序通过系统调用(syscall)或中断进入内核态,完成后返回用户态。
二、进程与线程:调度与并发模型
进程是 OS 资源分配的基本单位,线程是调度的基本单位。需掌握进程状态模型、调度算法、线程特性。
2.1 进程基本概念
进程是“程序的一次执行过程”,核心属性包括PCB(进程控制块)、状态、上下文:
进程属性 | 定义与作用 | 关键细节 |
---|---|---|
PCB | 进程的“身份证”,存储状态、优先级等信息 | 操作系统通过 PCB 管理进程 |
进程状态 | 就绪→运行→阻塞→终止的生命周期 | 阻塞态因 I/O 或同步事件触发 |
上下文 | 进程运行的环境(寄存器、内存、PC值) | 上下文切换是调度的核心开销 |
2.2进程三态模型:状态定义与转换逻辑
进程在生命周期中会在 运行态、就绪态、阻塞态 间动态切换,三态模型是理解进程调度的核心框架:
进程的每个状态对应“CPU 占用权”与“执行条件”的差异,核心特征如下:
进程状态 | 核心定义 | 典型场景示例 |
---|---|---|
运行态 | 获得 CPU 使用权,正在执行指令 | 浏览器渲染网页的进程 |
就绪态 | 具备运行条件,等待 CPU 调度 | 多个后台程序排队等待 CPU |
阻塞态(等待态/睡眠态) | 等待某事件完成(如 I/O、信号量),无法占用 CPU | 程序读取硬盘文件时的进程 |
三态间的转换由 调度策略、资源状态、事件完成 驱动,转换逻辑如下:
- 就绪态 → 运行态:CPU 调度器从就绪队列中选择进程,分配 CPU 使用权(触发条件:“被调度”);
- 运行态 → 就绪态:进程时间片耗尽,或高优先级进程进入就绪队列(触发条件:“时间片到”);
- 运行态 → 阻塞态:进程发起 I/O 请求、等待信号量等事件(触发条件:“等待某事件,如 I/O 请求”);
- 阻塞态 → 就绪态:等待的事件完成(如 I/O 结束、信号量释放)(触发条件:“等待的事件发生或 I/O 结束”)。
进程三态模型的转换关系可总结为:
就绪态 ──「被调度」──→ 运行态
运行态 ──「时间片到」──→ 就绪态
运行态 ──「等待事件(如 I/O)」──→ 阻塞态
阻塞态 ──「事件完成(如 I/O 结束)」──→ 就绪态
2.3 进程控制:创建与终止
进程通过原语完成创建、终止、阻塞、唤醒:
控制原语 | 功能描述 | 触发场景 |
---|---|---|
创建原语 | 分配资源、初始化 PCB | 用户登录、执行程序 |
终止原语 | 回收资源、撤销 PCB | 程序正常结束、异常崩溃 |
阻塞原语 | 进程从运行→阻塞态 | 等待 I/O 完成、信号量 P 操作 |
唤醒原语 | 进程从阻塞→就绪态 | I/O 完成、信号量 V 操作 |
2.4 线程:轻量级进程
线程是“轻量级进程”,与进程在资源共享、调度粒度、上下文切换上存在差异:
维度 | 进程(Process) | 线程(Thread) |
---|---|---|
资源分配单位 | 独立地址空间、文件句柄等资源 | 共享进程资源(地址空间、文件) |
调度单位 | OS 级调度(切换开销大) | CPU 级调度(切换开销小) |
并发性 | 进程间并发(需 IPC 通信) | 线程间并发(共享内存通信) |
2.5 进程间通信(IPC)
多进程协作需通过 IPC 共享数据,典型机制:
IPC 机制 | 实现原理 | 适用场景 |
---|---|---|
管道(Pipe) | 单向字节流,基于文件系统实现 | 父子进程间简单数据传输 |
消息队列 | 消息链表,支持多进程异步通信 | 分布式系统解耦通信 |
共享内存 | 内存区域映射,进程直接读写 | 高吞吐量数据共享 |
信号量 | 计数器+PV操作,实现同步互斥 | 临界资源访问控制 |
套接字(Socket) | 网络层通信接口,支持跨主机 | 分布式系统网络通信 |
三、同步与互斥:临界资源与 PV 操作
并发进程需通过同步机制避免“竞态条件”,核心是临界资源保护与PV 操作。
3.1 同步与互斥基本概念
术语 | 定义与作用 | 示例说明 |
---|---|---|
临界资源 | 一次仅允许一个进程访问的资源 | 打印机、共享变量 |
临界区 | 访问临界资源的代码段 | if (count > 0) { count--; } |
同步 | 进程间按序协作(如生产者-消费者) | 生产数据后通知消费 |
互斥 | 进程间互斥访问临界资源 | 打印机一次仅被一个进程使用 |
3.2 信号量与 PV 操作
信号量是“整型变量+等待队列”,通过 P(等待)、V(唤醒) 操作实现同步互斥:
- P 操作:
sem--; if (sem < 0) 阻塞进程
(申请资源); - V 操作:
sem++; if (sem <= 0) 唤醒进程
(释放资源)。
应试技巧
当信号量的类型是一个互斥资源的时候:PV会在一个程序段内出现
同步模型:对同一个信号量操作的PV是分布在两个不同的程序段内
PV是成对出现。如果没有成对出现,容易发生死锁
信号量的变化范围:都没运行~同时运行
3.3 经典同步问题
通过 PV 操作解决三类经典问题,理解同步逻辑:
(1)生产者-消费者问题
场景:生产者生产数据,消费者消费数据,共享缓冲区容量有限。
实现:用空缓冲区信号量(empty)、满缓冲区信号量(full)、互斥信号量(mutex) 协同:
// 生产者进程
while (true) {
P(empty); // 申请空缓冲区
P(mutex); // 进入临界区(操作缓冲区)
生产数据并放入缓冲区;
V(mutex); // 离开临界区
V(full); // 释放满缓冲区
}
// 消费者进程
while (true) {
P(full); // 申请满缓冲区
P(mutex); // 进入临界区
从缓冲区取出数据并消费;
V(mutex); // 离开临界区
V(empty); // 释放空缓冲区
}
(2)读者-写者问题
场景:多个读者可同时读,写者需独占资源(读-写互斥、写-写互斥)。
实现:用读计数(rc)、互斥信号量(mutex)、写信号量(wrt) 控制:
int rc = 0;
semaphore mutex = 1, wrt = 1;
// 读者进程
P(mutex);
rc++;
if (rc == 1) P(wrt); // 第一个读者锁写
V(mutex);
读操作;
P(mutex);
rc--;
if (rc == 0) V(wrt); // 最后一个读者解锁写
V(mutex);
// 写者进程
P(wrt);
写操作;
V(wrt);
(3)哲学家进餐问题
场景:五位哲学家围坐,需左右筷子吃饭,避免死锁。
实现:通过信号量数组(chopstick[5]) 与取筷策略(如限制同时拿筷人数) 解决死锁:
semaphore chopstick[5] = {1, 1, 1, 1, 1};
semaphore mutex = 1; // 互斥取筷
// 哲学家 i 进程
while (true) {
P(mutex);
P(chopstick[i]); // 拿左筷
P(chopstick[(i+1)%5]); // 拿右筷
V(mutex);
进餐;
V(chopstick[i]); // 放左筷
V(chopstick[(i+1)%5]); // 放右筷
思考;
}
四、死锁:定义、条件与处理策略
死锁是“进程循环等待资源”的僵局,需掌握必要条件、处理策略。
4.1 死锁必要条件
死锁发生需同时满足互斥、持有并等待、不可剥夺、循环等待四个条件:
条件 | 定义与特征 | 破坏方式 |
---|---|---|
互斥使用 | 资源一次仅被一个进程占用 | 资源虚拟化(如共享打印机) |
持有并等待 | 进程占资源并等待其他资源 | 预分配所有资源(启动前申请) |
不可剥夺 | 资源仅能被持有进程主动释放 | 强制剥夺资源(如 OS 重启进程) |
循环等待 | 进程间形成资源请求环 | 资源有序分配(按编号申请) |
4.2 死锁处理策略
针对死锁的四个处理阶段,策略分为四类:
策略类型 | 核心逻辑 | 典型算法 |
---|---|---|
死锁预防 | 破坏死锁必要条件(如预分配) | 资源有序分配法 |
死锁避免 | 运行时检测资源分配安全性 | 银行家算法(安全序列检测) |
死锁检测 | 定期检测死锁并标记 | 资源分配图化简法 |
死锁解除 | 终止进程或剥夺资源恢复系统 | 终止代价最小的进程 |
4.3 死锁临界值与系统不死锁的资源计算
通过“资源分配的临界值分析”,可定量判断系统是否存在死锁风险。核心逻辑与公式如下:
(1)核心原理:资源预分配的“安全阈值”
若系统满足以下条件,则不会发生死锁:
给系统中每一个进程分配其所需资源的最大数少一个资源后,系统仍有至少一个剩余资源。
(2)死锁临界值公式:数学建模与示例
假设系统有 ( m ) 个同类资源,被 ( n ) 个进程共享,每个进程最多请求 ( k ) 个资源。通过“轮流分配资源”的场景建模,可推导死锁临界值:
① 公式概述与死锁场景示例
② 不死锁的最小资源数公式
(3)通用资源计算逻辑
系统不发生死锁的资源分配需满足:
该式等价于“死锁临界值公式”,本质是通过预分配资源的“安全冗余”,确保总有一个进程能完成资源请求,打破循环等待。
4.4 进程资源图:死锁的可视化检测工具
进程资源图是死锁检测的核心工具,通过图形化方式直观呈现“进程-资源”的请求、分配关系,辅助判断系统是否陷入死锁。
五、内存管理:分区、分页与虚拟内存
内存是操作系统资源管理的核心载体,需围绕**“空间分配、地址转换、内存保护、虚拟扩展”** 四大目标,掌握分区管理、分页/分段、虚拟内存等核心技术。
5.1 内存管理核心目标
内存管理需平衡“资源利用率、访问效率、系统开销”,四大核心目标如下:
目标维度 | 技术价值 | 典型实现手段 |
---|---|---|
空间分配 | 高效划分内存,支持多进程并发 | 分区管理、分页/分段存储 |
地址转换 | 屏蔽物理内存细节,实现进程隔离 | 页表、段表、虚拟地址映射 |
内存保护 | 防止进程越界访问,保障安全性 | 基址/限长寄存器、页表权限位 |
虚拟扩展 | 用磁盘扩展内存,突破物理限制 | 虚拟内存、页面置换算法 |
5.2 分区存储管理:早期连续分配方案
分区管理是内存管理的初代技术,将物理内存划分为连续区域分配给进程,分固定分区、动态分区两类:
5.2.1 固定分区管理
- 核心逻辑:系统启动前,将内存预先划分为若干大小固定的分区,每个分区仅能分配给一个进程;
- 典型问题:易产生内部碎片(进程大小 < 分区大小,剩余空间无法利用);
- 适用场景:早期单道/多道批处理系统(如 IBM OS/360)。
5.2.2 动态分区管理
- 核心逻辑:进程加载时按需动态划分内存,进程结束后回收分区;
- 典型问题:易产生外部碎片(分区回收后形成分散空闲块,无法满足大进程需求);
- 分配算法:
算法类型 核心逻辑 性能特点 首次适应(FF) 从内存起始位置找首个能满足的分区 简单高效,但低地址碎片多 最佳适应(BF) 选择最小的能满足需求的分区 减少内部碎片,但外部碎片多 最坏适应(WF) 选择最大的空闲分区拆分 减少外部碎片,但大分区浪费 循环首次适应(NF) 从上次查找位置继续,循环搜索能满足的分区 平衡低地址碎片问题
5.3 页式存储管理:离散分配的里程碑
页式存储通过**“分页(逻辑地址)+ 分块(物理内存)”** 实现离散分配,解决了分区管理的“连续分配刚性”问题,核心是“页表+地址转换”。
5.3.1 核心概念与结构
页式存储将内存与进程地址空间拆解为等长的“页(Page)”与“块(Frame)”,通过页表(Page Table) 映射逻辑页→物理块:
术语 | 定义与作用 | 示例(32位地址、4KB页大小) |
---|---|---|
页(Page) | 进程逻辑地址的离散单位(用户视角) | 进程地址被划分为若干4KB页 |
块(Frame) | 物理内存的离散单位(硬件视角) | 物理内存划分为若干4KB块 |
页表 | 记录“页号→块号”映射关系的表 | 页号 0 对应块号 2 、页号 1 对应块号 6 |
5.3.2 地址结构与转换
页式存储的逻辑地址由 “页号(Page No.) + 页内地址(Offset)” 组成,物理地址由 “块号(Frame No.) + 页内地址(Offset)” 组成。
以“32位地址、4KB(( 2^{12} ) 字节)页大小”为例:
- 逻辑地址拆分:前20位为页号(可表示 ( 2^{20} ) 个页),后12位为页内地址(覆盖4KB页内空间);
- 地址转换流程:CPU 取逻辑地址→拆分页号+页内地址→查页表获取块号→拼接块号+页内地址→得到物理地址。
5.3.3 技术特点
页式存储通过“离散分配+页表映射”优化内存,但也存在系统开销:
优势 | 劣势 |
---|---|
无外部碎片(块离散分配,无连续空隙) | 页表增加系统内存开销(每个进程需维护页表) |
分配/管理简单(页大小固定,算法统一) | 存在内部碎片(最后一页未完全使用的空间) |
5.4 段式存储管理:按程序逻辑划分
段式存储以**“程序逻辑段(如代码段、数据段、栈段)”** 为单位分配内存,核心是“段表+段内连续”,更贴合程序开发逻辑。
5.4.1 核心概念与结构
段式存储将进程地址空间按逻辑功能划分为不等长的“段(Segment)”,通过段表(Segment Table) 映射段→物理内存区域:
术语 | 定义与作用 | 示例(编译器视角) |
---|---|---|
段(Segment) | 进程逻辑地址的连续单位(按程序逻辑划分) | 代码段(.text)、数据段(.data)、栈段(.stack) |
段表 | 记录“段号→物理起始地址+段长”的表 | 段号 0 对应起始地址 0x1000 、段长 4KB |
5.4.2 技术特点
段式存储更贴合程序逻辑,但内存管理复杂度更高:
优势 | 劣势 |
---|---|
无内部碎片(段内连续,按需分配长度) | 易产生外部碎片(段间不连续,空闲块分散) |
支持程序段共享(如共享库、动态链接库) | 分配/管理复杂(段大小不固定,需动态调整) |
5.5 段页式存储管理:分段+分页的混合方案
段页式存储结合“段式的逻辑划分”与“页式的离散分配”,核心是**“先分段、再分页”**,平衡了“逻辑合理性”与“内存利用率”。
5.5.1 核心流程与地址转换
段页式存储的地址转换需经过**“段表→页表→物理地址”** 两层映射:
- 逻辑地址拆分:程序先按逻辑划分为段,段内再划分为页,逻辑地址拆解为「段号 + 段内页号 + 页内地址」;
- 段表查询:通过段号查段表,获取“段内页表的基地址”;
- 页表查询:通过段内页号查页表,获取“物理块号”;
- 物理地址合成:块号 + 页内地址 → 最终物理地址。
5.5.2 技术特点
段页式存储是“折中方案”,系统开销与功能复杂度最高:
优势 | 劣势 |
---|---|
内存利用率高(页式离散分配,无外部碎片) | 段表+页表双重开销,系统内存/性能消耗大 |
支持程序段共享(段式逻辑划分) | 地址转换流程复杂,需多次查表(缓存 TLB 可优化) |
5.6 虚拟内存与页面置换(补充扩展方向)
虚拟内存通过**“磁盘作为内存扩展层”,实现“部分装入、按需调页”,核心是页面置换算法**(如 FIFO、LRU、时钟算法),需结合“缺页中断、页框分配”等机制协同工作。
六、文件系统:组织、存储与访问
文件系统是“外存数据的管理接口”,需掌握文件结构、目录结构、存储管理。
6.1 文件与目录结构
文件是“命名的字节序列”,目录是“文件的索引”,核心结构:
结构类型 | 定义与示例 | 访问效率 |
---|---|---|
文件结构 | 无结构(二进制)、有结构(记录式) | 数据库文件(记录式) |
目录结构 | 单级、多级(树状)、无环图 | Linux 树状目录(/etc、/home) |
6.2 文件存储管理
外存空闲空间管理与文件分配是核心,典型技术:
管理方式 | 实现原理 | 适用场景 |
---|---|---|
空闲块链表 | 链表串联空闲块,分配/回收高效 | 大型文件系统 |
位示图 | 二进制位标记块状态,空间紧凑 | 嵌入式系统 |
索引分配 | 索引块记录文件块位置,支持大文件 | 数据库、多媒体文件 |
如果这篇考点拆解帮你理清了知识脉络,点击右上角「关注」,后续将输出更多软件测试技术干货