操作系统核心:从进程线程到调度算法,这一篇就够了
目录
前言
一、进程与线程:程序为什么需要“动”起来?
1.1 程序的两种执行方式
1.2 进程:资源分配的基本单位
1.3 线程:CPU调度的最小单位
1.4 进程与线程的对比(面试高频)
二、进程的状态与转换:进程的一生
2.1 七种状态详解
2.2 挂起状态的深入理解
2.3 状态转换的关键规则
三、线程的实现:三种映射模型
3.1 用户级线程(ULT)
3.2 内核级线程(KLT)
3.3 三种映射模型对比
四、进程的组织与控制:PCB是关键
4.1 进程的组成
4.2 PCB的作用
4.3 PCB的三种组织方式
4.4 进程控制的主要操作
五、进程间通信(IPC):进程怎么聊天?
5.1 共享存储器系统
5.2 消息传递
5.3 管道通信
5.4 信号
六、CPU调度与调度算法
6.1 调度的层次
6.2 调度算法的评价指标
6.3 七种调度算法详解
6.3.1 先来先服务(FCFS)
6.3.2 短作业优先(SJF)
6.3.3 优先级调度(PR)
6.3.4 高响应比优先(HRRN)
6.3.5 时间片轮转(RR)
6.3.6 多级队列调度(MLQ)
6.3.7 多级反馈队列调度(MLFQ)⭐
七、知识体系总结
后记
前言
最近系统性地整理了操作系统进程管理模块的知识,发现这块内容虽然基础,但知识点密集、概念容易混淆——用户级线程和内核级线程有什么区别?多级队列和多级反馈队列的核心差异是什么?进程的七种状态之间如何转换?
这篇文章将按照“进程与线程 → 状态转换 → 线程实现 → 进程控制 → 进程间通信 → CPU调度”的逻辑主线,把零散的知识点串联成一个完整的知识体系。适合正在准备操作系统考试、面试或想系统梳理这部分知识的同学阅读。
阅读建议:全文约5000字,建议先看目录定位自己需要的章节,按需阅读。
一、进程与线程:程序为什么需要“动”起来?
1.1 程序的两种执行方式
程序的执行过程可以分为顺序执行和并发执行两种方式。
顺序执行的特征:顺序性、封闭性、可再现性。程序按代码顺序一条条执行,像流水线一样稳定可预测。
并发执行则完全不同,它带来了三个新特征:
间断性:程序走走停停,不是一口气跑完
失去封闭性:多个程序共享全机资源,执行状态受外界环境影响
不可再现性:同样的输入,多次运行可能得到不同结果
正是为了解决并发执行带来的这些问题,操作系统才引入了进程这个概念。
1.2 进程:资源分配的基本单位
进程的定义:进程是程序的一次执行,是程序的实体;是系统进行资源分配和调度的基本单位。
进程的五大特征:
| 特征 | 含义 |
|---|---|
| 结构性 | 由程序段、数据段、PCB三部分组成,PCB是进程存在的唯一标志 |
| 动态性 | 进程具有生命周期(创建→运行→消亡) |
| 并发性 | 宏观并行、微观串行 |
| 独立性 | 进程是资源分配与调度的基本单位,拥有独立资源 |
| 异步性 | 进程以不可预知的速度前进 |
进程与程序的区别(常考):
| 对比维度 | 进程 | 程序 |
|---|---|---|
| 本质 | 程序的一次执行实例 | 静态的指令集合 |
| 状态 | 活动的、有生命周期 | 静态的、存储在磁盘 |
| 关系 | 进程包含程序的代码部分 | 程序是进程的代码来源 |
| 存储位置 | 内存中 | 外存中 |
1.3 线程:CPU调度的最小单位
线程的定义:线程是进程内部的一个基本执行单元,是操作系统进行CPU调度的最小单位。
线程的四大特征:
轻型实体:基本不拥有系统资源,只有保证独立运行的最少资源
独立调度和分派的基本单位:在多线程OS中,线程是能独立运行的基本单位
可并发执行:同一进程的多个线程可以并发执行
共享进程资源:同一进程中的各个线程共享该进程所拥有的资源
1.4 进程与线程的对比(面试高频)
| 对比维度 | 进程 | 线程 |
|---|---|---|
| 调度单位 | 资源分配的基本单位 | CPU调度的基本单位 |
| 拥有资源 | 拥有独立的系统资源 | 基本不拥有资源,共享进程资源 |
| 独立性 | 进程间独立性高 | 同一进程的线程间独立性低 |
| 系统开销 | 创建/撤销/切换开销大 | 创建/撤销/切换开销小 |
| 并发性 | 进程间可并发 | 同一进程的线程间也可并发 |
一句话总结:进程是资源拥有的基本单位,线程是CPU调度的基本单位。进程是“容器”,线程是容器里真正干活的“人”。
二、进程的状态与转换:进程的一生
2.1 七种状态详解
进程在其生命周期中会经历多种状态,理解这些状态及其转换条件是理解操作系统调度机制的基础。
| 状态 | 含义 | 触发条件 |
|---|---|---|
| 创建态 | 进程正在被创建 | 用户登录、作业调度、应用请求等 |
| 就绪态 | 已获得除CPU外的所有资源,等待调度 | 创建完成/被唤醒后 |
| 运行态 | 正在CPU上执行 | 被调度器选中 |
| 阻塞态 | 因等待某事件而暂时无法执行 | 请求I/O、等待资源等 |
| 终止态 | 执行结束,系统正在回收资源 | 正常结束/异常/外界干预 |
| 挂起态 | 从内存移到外存,释放资源 | 终端用户请求、负荷调节等 |
| 激活态 | 从外存调回内存,恢复运行 | 挂起的逆操作 |
2.2 挂起状态的深入理解
挂起是指操作系统通过特定原语将进程从内存暂时转移到外存,使其脱离CPU调度范围的操作。挂起后的进程不再参与系统调度,直到被激活为止。
挂起的常见原因:
终端用户请求
父进程请求
负荷调节需要
操作系统需要
2.3 状态转换的关键规则
创建态 → 就绪态(资源分配完成) 就绪态 → 运行态(被调度器选中) 运行态 → 就绪态(时间片用完/被抢占) 运行态 → 阻塞态(等待I/O或资源) 阻塞态 → 就绪态(等待的事件完成) 运行态 → 终止态(执行结束/异常终止) 任何状态 → 挂起态(被主动挂起) 挂起态 → 激活态(被唤醒调回)
核心记忆点:就绪→运行由调度程序决定,运行→阻塞是进程主动行为,阻塞→就绪由事件完成触发。
三、线程的实现:三种映射模型
线程的实现方式决定了线程的调度效率、并发能力和系统开销。主要有三种模型。
3.1 用户级线程(ULT)
定义:不依赖操作系统内核,由应用程序利用线程库提供的操作控制的线程。内核只知道进程的存在,调度单位是进程。
优点:
线程切换在用户空间完成,不需要切换到内核态,开销小
调度算法可以进程专用
线程实现与OS无关,可移植性好
缺点:
一个用户级线程被阻塞后,整个进程都会被阻塞
多个线程不可在多核处理机上并行运行
3.2 内核级线程(KLT)
定义:依赖于内核,由操作系统内核完成创建和撤销工作的线程。在内核空间实现。
优点:
多处理机系统中,内核可同时调度同一进程的多个线程 →真正的并行
一个线程阻塞了,内核可调度该进程的其他线程
内核本身可以采用多线程技术
缺点:
线程切换需要内核参与,必须从用户态切换到内核态,开销大
创建、销毁、挂起、唤醒等操作开销较大
依赖内核调度策略,灵活性降低
3.3 三种映射模型对比
| 模型 | 映射关系 | 优点 | 缺点 | 典型代表 |
|---|---|---|---|---|
| 一对一 | 1个ULT → 1个KLT | 并行能力强,阻塞问题少 | 开销大,创建数量受限 | Linux NPTL、Windows |
| 多对一 | 多个ULT → 1个KLT | 开销低,自定义调度 | 一个阻塞全进程卡死 | 早期Green Threads |
| 多对多 | n个ULT → m个KLT | 资源利用率高,灵活调度 | 实现复杂,负载均衡难 | Go goroutine |
记忆口诀:一对一够硬核(并行强但耗资源),多对一够轻量(切换快但怕阻塞),多对多最聪明(兼顾两者但难实现)。
四、进程的组织与控制:PCB是关键
4.1 进程的组成
进程由三部分组成:
程序段:要执行的指令
数据段:指令操作的数据
进程控制块(PCB):进程存在的唯一标志,常驻内存
4.2 PCB的作用
作为独立运行基本单位的标志
实现间断式的运行方式(保存切换时的现场信息)
提供进程管理、调度所需的信息
实现与其他进程的同步与通信
4.3 PCB的三种组织方式
| 组织方式 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 线性方式 | 所有PCB放在一张线性表中 | 实现简单,开销小 | 每次查找需扫描整张表 |
| 链接方式 | 按状态分为多个链表 | 分类管理高效,动态管理好 | 链表操作需维护指针 |
| 索引方式 | 为不同状态建索引表 | 查找速度快,支持随机访问 | 需额外存储空间 |
4.4 进程控制的主要操作
| 操作 | 触发事件 | 核心动作 |
|---|---|---|
| 创建 | 用户登录、作业调度、应用请求 | 申请PCB→分配资源→初始化PCB→入就绪队列 |
| 终止 | 正常结束、异常结束、外界干预 | 停止运行→回收资源→移除PCB |
| 阻塞 | 请求资源失败、等待操作完成 | 保护现场→转为阻塞态→入等待队列 |
| 唤醒 | 等待的事件发生 | 从等待队列移除→转为就绪态→入就绪队列 |
| 挂起 | 用户请求、负荷调节 | 修改状态→数据换出外存→更新资源记录 |
| 激活 | 挂起的逆操作 | 数据调入内存→修改状态→入相应队列 |
| 切换 | 调度决策 | 保存当前上下文→更新PCB→选择新进程→恢复上下文 |
五、进程间通信(IPC):进程怎么聊天?
进程间通信是指进程之间的信息交换。主要有以下几种方式:
5.1 共享存储器系统
原理:在通信进程之间建立一块可直接访问的共享存储空间。
两种类型:
基于共享数据结构:粒度精细,用队列、栈等特定结构通信(低级通信)
基于共享存储区:粒度粗,用一块连续的无格式内存区域(高级通信,数据量大)
5.2 消息传递
原理:以格式化消息为单位,通过内核作为中介传递。
两类方式:
直接通信:发送方和接收方直接指定对方ID,一对一传递
间接通信:通过中间媒介(如信箱)传递
5.3 管道通信
原理:pipe是指用于连接读/写进程的共享文件,本质是内核维护的一块内存缓冲区。
三大特性:
伪文件属性:数据存储在内核缓冲区中,通过文件描述符访问
半双工通信:默认单向传输
字节流传输:无结构,需自行处理数据拆分
管道机制需提供的三种协调能力:
互斥:同一时间只有一个进程操作管道
同步:协调读写速度
确定对方状态:保证数据传输的可靠性
分类:
匿名管道:仅支持有亲缘关系的进程(父子、兄弟)
命名管道:通过管道文件实现任意进程间通信
5.4 信号
定义:信号是进程间通信机制中唯一的异步通信机制,可以在任何时候发送信号给某一进程,无须知道该进程的状态。
关键点:信号是异步的,发送方不需要等待接收方就绪。
六、CPU调度与调度算法
6.1 调度的层次
| 调度类型 | 调度对象 | 作用 | 出现频率 |
|---|---|---|---|
| 高级调度(长程/作业调度) | 作业 | 将外存作业调入内存,创建进程 | 低 |
| 低级调度(短程/进程调度) | 进程 | 决定就绪队列中哪个进程获得CPU | 最高(必不可少) |
注意:实时系统和分时系统不设置高级调度,因为交互式系统需要“随到随进”,实时系统需要确定的响应时间。
6.2 调度算法的评价指标
| 指标 | 定义 | 公式 |
|---|---|---|
| CPU利用率 | CPU有效工作时间占比 | 有效时间/(有效时间+空闲时间) |
| 系统吞吐量 | 单位时间内完成的作业数量 | — |
| 周转时间 | 从提交到完成的时间间隔 | 完成时间 - 到达时间 |
| 带权周转时间 | 周转时间与服务时间之比 | T/Ts |
| 等待时间 | 在就绪队列中等待的总时间 | — |
| 响应时间 | 从提交到首次获得CPU的时间 | — |
6.3 七种调度算法详解
6.3.1 先来先服务(FCFS)
原理:按作业/进程到达的先后次序调度。
特点:实现简单,但对短作业不利( convoy effect 护航效应)。
6.3.2 短作业优先(SJF)
原理:选择估计运行时间最短的作业/进程。
两种模式:
非抢占式SJF:运行时间相同时按FCFS
抢占式SJF(最短剩余时间优先):有新进程剩余时间更短时抢占
特点:平均等待时间最短,但需要预知运行时间,长作业可能饥饿。
6.3.3 优先级调度(PR)
原理:基于作业/进程的紧迫程度赋予优先级。
两种类型:
非抢占式
抢占式
优缺点:
✅ 实现简单,考虑了紧迫程度
❌低优先级可能永远得不到运行(饥饿)
6.3.4 高响应比优先(HRRN)
原理:响应比 Rp = (等待时间 + 要求服务时间) / 要求服务时间 = 1 + 等待时间/要求服务时间
特点:只用于作业调度,兼顾了等待时间和运行时间,长作业等待久了也能获得服务,不会饥饿。
6.3.5 时间片轮转(RR)
原理:所有进程按FCFS排队,每个进程运行一个时间片后重新排队。
切换时机:
进程运行结束
时间片用完
特点:响应时间快,适合分时系统;但时间片大小选择关键——太短则切换开销大,太长则退化为FCFS。
6.3.6 多级队列调度(MLQ)
原理:将就绪队列分为若干个,不同性质的进程固定分在不同队列,不同队列采用不同调度算法,不允许跨队列。
核心本质:静态分类、刚性隔离——进程“出身定终身”。
6.3.7 多级反馈队列调度(MLFQ)⭐
原理:在多个优先级队列基础上,允许进程根据运行时行为动态迁移。采用“奖惩机制”:消耗完时间片的进程降级,主动让出CPU(如I/O操作)的进程升级,配合“老化”机制防止饥饿。
核心本质:动态学习、柔性适应——“看表现定待遇”。
MLQ vs MLFQ 核心区别:
| 对比维度 | MLQ | MLFQ |
|---|---|---|
| 进程归属 | 静态固定,至死不变 | 动态浮动,能升能降 |
| 决策依据 | 外部属性(进程类型) | 内部行为(CPU/I/O占比) |
| 饥饿问题 | 低优先级可能饿死 | 有老化机制防止饥饿 |
| 管理方式 | 需管理员手动配置 | 全自动,内核自适应 |
一句话总结:MLQ是“出身定终身”,MLFQ是“看表现定待遇”。MLFQ的本质是MLQ + 进程迁移规则 + 老化机制。
七、知识体系总结
把这六个模块串起来,就形成了完整的进程管理知识体系:
用户程序(用户态) ↓ 系统调用/中断/异常 内核态调度器(MLFQ等算法) ↓ 选择进程/线程 进程状态转换(就绪→运行→阻塞→...) ↓ 线程实现模型(决定并发能力) ↓ 进程间通信(共享内存/消息/管道/信号)
核心要点回顾:
进程是资源分配单位,线程是CPU调度单位
用户级线程切换快但阻塞影响大,内核级线程支持真并行但开销大
七态转换中,挂起是主动移出内存,阻塞是等待事件
MLFQ是MLQ的进化版,核心是“动态反馈”
实时和分时系统没有高级调度
后记
这篇文章整理了进程管理模块的核心知识点,涵盖了从基础概念到调度算法的完整脉络。如果你正在准备考试或面试,建议重点掌握:
进程与线程的对比
三种线程映射模型的优劣
MLQ与MLFQ的区别
七态转换的触发条件
写作说明
本文内容源自笔者近期系统学习操作系统进程管理时的个人笔记。为了提升阅读体验,笔者借助AI工具对原始笔记进行了逻辑梳理、表格优化和排版润色,但所有核心知识点均经过笔者逐一核对与校正。如有疏漏,欢迎指正交流。
