跳转至

多道程序设计

来源:操作系统 / note/进程管理/进程/多道程序设计.md

多道程序设计可以理解为:

内存里同时放入多个程序,让 CPU 在它们之间切换执行,从而提高 CPU 和系统资源利用率。

它是现代操作系统并发执行的基础。


1. 为什么需要多道程序设计?

早期计算机一次只能运行一个程序,叫单道程序设计

比如程序 A 运行时:

程序 A:计算一会儿 → 等磁盘读数据 → 再计算 → 等打印机输出

问题是:
当程序 A 在等待磁盘、键盘、打印机这些 I/O 操作时,CPU 是空闲的

举个例子:

CPU 很快
磁盘很慢

如果程序要等磁盘读文件,CPU 可能等很久。这样计算机资源就浪费了。

于是操作系统引入了多道程序设计

程序 A 等磁盘时,CPU 去运行程序 B
程序 B 等键盘时,CPU 去运行程序 C
程序 C 时间片到了,CPU 再切回程序 A

这样 CPU 尽量不闲着。


2. 多道程序设计的核心思想

核心思想是:

把多个作业或进程同时放入内存,由操作系统调度它们交替使用 CPU。

注意,这里的“同时运行”不一定是真的物理同时。

在单核 CPU 上:

某一瞬间只能执行一个进程

但是 CPU 切换速度很快,所以用户感觉多个程序在同时运行。

比如你一边听歌,一边写代码,一边下载文件:

音乐播放器
VSCode
浏览器
下载程序

它们看起来都在运行,实际上 CPU 在它们之间快速切换。


3. 单道程序 vs 多道程序

单道程序设计

内存中一次只有一个程序

执行过程:

程序 A 运行
程序 A 等 I/O,CPU 空闲
程序 A 继续运行
程序 A 结束
程序 B 才开始

缺点:

CPU 利用率低
内存利用率低
设备利用率低
系统吞吐量低

多道程序设计

内存中同时有多个程序

执行过程:

程序 A 运行
程序 A 等 I/O
CPU 切到程序 B
程序 B 等 I/O
CPU 切到程序 C
程序 A 的 I/O 完成
CPU 再切回程序 A

优点:

CPU 利用率提高
内存利用率提高
I/O 设备和 CPU 可以并行工作
系统吞吐量提高

4. 用一个例子理解

假设有两个程序:

程序 A:计算 2 秒,等待磁盘 5 秒,再计算 2 秒
程序 B:计算 3 秒,等待键盘 4 秒,再计算 3 秒

如果是单道程序:

先运行 A:
A 计算 2 秒
A 等磁盘 5 秒,CPU 空闲
A 计算 2 秒

再运行 B:
B 计算 3 秒
B 等键盘 4 秒,CPU 空闲
B 计算 3 秒

总时间:

2 + 5 + 2 + 3 + 4 + 3 = 19 秒

其中 CPU 空闲了:

5 + 4 = 9 秒

如果是多道程序:

A 等磁盘时,CPU 去运行 B
B 等键盘时,CPU 可以切回 A

这样 CPU 空闲时间减少,总体效率提高。


5. 多道程序设计和进程的关系

多道程序设计要实现,操作系统必须引入进程模型

因为内存里同时有多个程序,操作系统必须知道:

哪个程序正在运行?
哪个程序在等待?
哪个程序已经准备好?
哪个程序占用了哪些资源?

所以操作系统用 PCB,进程控制块 来管理每个进程。

也就是:

多道程序设计需要进程管理
进程管理依靠 PCB
CPU 切换依靠上下文切换

6. 多道程序设计中的状态切换

在多道程序环境下,进程会在几个状态之间切换:

就绪态
运行态
阻塞态

比如:

进程 A 正在运行
进程 A 请求磁盘 I/O
进程 A 进入阻塞态
CPU 调度进程 B 运行
进程 A 的 I/O 完成
进程 A 回到就绪态
等待下一次被 CPU 调度

图可以这样理解:

        调度
就绪态 --------> 运行态
  ^              |
  |              | 请求 I/O
  |              v
  +----------- 阻塞态
      I/O 完成

这就是多道程序能提高效率的关键:
一个进程阻塞时,CPU 不等它,而是去运行别的进程。


7. 多道程序设计需要解决的问题

多道程序设计虽然提高效率,但也带来了很多问题。

第一,CPU 调度问题

内存里有多个就绪进程:

进程 A 准备好了
进程 B 准备好了
进程 C 准备好了

CPU 应该先运行谁?

这就需要调度算法,比如:

先来先服务 FCFS
短作业优先 SJF
时间片轮转 RR
优先级调度

第二,内存管理问题

多个程序同时在内存中,操作系统要防止它们互相破坏。

比如:

进程 A 不能随便修改进程 B 的内存

所以需要:

地址空间隔离
分页
分段
虚拟内存

第三,资源竞争问题

多个进程可能同时访问同一个资源。

比如:

两个进程同时写同一个文件
两个进程同时打印
两个进程同时修改一个变量

这就需要:

互斥
同步
信号量
管程

你之前 miniFS 里的:

writer_pid
reader_count

就是在解决多个进程访问同一个文件时的冲突。


第四,死锁问题

多个进程互相等待资源,可能造成死锁。

例如:

进程 A 占有打印机,等待磁盘
进程 B 占有磁盘,等待打印机

结果:

A 等 B
B 等 A
谁也走不了

这就是死锁。


8. 多道程序设计和分时系统的区别

这两个概念容易混。

多道程序设计

重点是:

提高资源利用率

主要面向批处理系统。

多个作业同时进入内存,谁能运行由系统调度。


分时系统

重点是:

让多个用户交互式使用计算机

它通常使用时间片轮转:

每个用户程序运行一小段时间
然后切换到下一个

用户感觉自己独占计算机。

所以关系是:

多道程序设计是基础
分时系统是在多道程序基础上发展出来的

9. 多道程序设计的优点

主要有三个:

提高 CPU 利用率
提高系统吞吐量
提高 I/O 设备和 CPU 的并行程度

比如:

进程 A 使用 CPU
进程 B 使用磁盘
进程 C 等待键盘输入

这些可以在同一段时间内交错进行。


10. 多道程序设计的缺点

它也让操作系统更复杂:

需要进程调度
需要内存保护
需要资源分配
需要同步互斥
可能产生死锁
需要上下文切换

其中上下文切换本身也有开销:

保存当前进程状态
恢复另一个进程状态
切换地址空间
更新调度信息

所以多道程序不是程序越多越好。

如果进程太多,CPU 可能大量时间都花在切换上,反而效率下降。


11. 一句话总结

多道程序设计就是:

把多个程序同时放入内存,当一个程序等待 I/O 或暂时不能运行时,操作系统切换去运行另一个程序,从而提高 CPU、内存和 I/O 设备的利用率。

它解决的是:

不要让 CPU 因为一个程序等待 I/O 而闲着

它带来的核心机制是:

进程
PCB
状态转换
CPU 调度
内存保护
同步互斥
死锁处理