Appearance
操作系统概述:并发、共享、虚拟、异步
概念
操作系统(Operating System, OS)是控制和管理整个计算机系统的硬件与软件资源、合理组织调度计算机的工作与资源分配、进而为用户和其他软件提供方便接口与环境的程序集合。
三句话概括它的三个身份:
| 身份 | 说法 | 落点 |
|---|---|---|
| 管理者 | 管理处理器、存储器、文件、设备四类资源 | "一台机器怎么变成很多台机器" |
| 服务员 | 给应用程序提供接口(命令接口 + 程序接口) | 用户不用碰硬件就能用计算机 |
| 扩展机器 | 把裸机"包装"成一台更好用的虚拟机器 | 硬件之上加了一层抽象 |
一句话说清它是什么:操作系统是硬件与应用程序之间的那层"管家 + 翻译"。它向下管住硬件,向上提供统一、方便、安全的接口。
这是主线【由硅到 C】的倒数第二站。前面五门课都在回答"硬件怎么工作",从这一门开始回答"怎么让硬件同时服务很多人、很多事"。
原理
一、四大特征(本章核心)
┌──────────────────────────────────────┐
│ 并发 ──→ 共享 (互为存在条件) │
│ ↕ ↕ │
│ 虚拟 ──→ 异步 │
└──────────────────────────────────────┘| 特征 | 一句话定义 | 关键细节 |
|---|---|---|
| 并发 | 多个程序在同一时间段内"交替"运行 | 注意是交替,不是同时;同一时刻仍只有一道程序在用 CPU |
| 共享 | 系统中的资源可供内存中多个并发执行的进程共同使用 | 分互斥共享与同时共享两种 |
| 虚拟 | 把一个物理实体变成多个逻辑对应物 | 分时分复用(虚拟处理器)与空分复用(虚拟存储器) |
| 异步 | 进程走走停停、以不可预知的速度向前推进 | 是并发的必然结果——大家都想用 CPU,只能轮流 |
⚠️ 并发与共享"互为存在条件"(必考):
- 没有并发,就谈不上共享:只有一个程序在跑,它独占全部资源,不存在"共享"这回事。
- 没有共享,并发也进行不下去:多个程序同时想用打印机却不让共享,那只能串行,等于没有并发。
并发与并行的区别(第一大易错点):
| 并发 concurrency | 并行 parallelism | |
|---|---|---|
| 定义 | 同一时间段内多个程序交替运行 | 同一时刻有多个程序在真正同时运行 |
| 硬件要求 | 单核即可(靠分时切换) | 必须多核 / 多处理器 |
| 微观瞬间 | 只有一个在跑 | 多个同时在跑 |
| 关系 | 并发是宏观同时、微观串行 | 并行是宏观与微观都同时 |
共享的两种类型:
| 类型 | 含义 | 例子 |
|---|---|---|
| 互斥共享 | 一段时间内只允许一个进程访问 | 打印机、摄像头、read 同一个文件的前半段 |
| 同时共享 | 一段时间内允许多个进程"同时"(宏观)访问 | 磁盘文件(可多个进程同时读)、可重入代码段 |
二、虚拟:把一个变多个
| 类型 | 做法 | 典型例子 |
|---|---|---|
| 时分复用 | 把时间切成小片轮流分给多个作业 | 虚拟处理器(一个 CPU 让每个进程都以为自己有 CPU);虚拟设备(SPOOLing 把一台打印机变多台) |
| 空分复用 | 把空间切块,每个作业用其中一块 | 虚拟存储器(每个进程都以为自己独占整个地址空间) |
虚拟的本质是"欺骗":让每个使用者都以为资源是"它一个人的"。代价是性能——虚拟存储器一旦缺页,就要等磁盘(见下例 2)。
三、异步:走走停停
异步 = 进程以不可预知的速度向前推进。 因为:
异步带来的核心难题:程序执行的"结果"依赖于时序——同样两个进程,谁先做、谁后做,可能得到完全不同的结果。这正是"同步与互斥"(os/12-sync.md)要解决的问题。
四、发展历程(四个主要阶段)
| 阶段 | 特征 | 解决的问题 | 新问题 |
|---|---|---|---|
| 手工操作 | 人工插板/纸带 | — | 慢,CPU 等人 |
| 批处理(单道) | 一批作业自动衔接 | 减少人工干预 | CPU 与 I/O 串行,浪费大 |
| 批处理(多道) | 内存同时放多道作业 | CPU 与 I/O 并行,利用率提高 | 无交互,作业平均周转时间长 |
| 分时 | 时间片轮转 | 人机交互、多用户共享 | 不能保证及时响应 |
| 实时 | 按优先级立即响应 | 在严格时限内完成(工业控制、导弹) | 吞吐率低 |
多道批处理的三个必记问题(这是"多道"的代价):
- 平均周转时间长(用户提交后要等)
- 无交互能力(用户不能干预)
- 资源分配与作业调度复杂
五、操作系统的五大功能
┌──────────── 操作系统功能 ────────────┐
│ 1 处理机管理(进程管理) │ ← 谁用 CPU、用多久
│ 2 存储器管理 │ ← 谁用哪块内存
│ 3 文件管理 │ ← 数据怎么组织、怎么按名访问
│ 4 设备管理 │ ← 外设怎么接、怎么分配
│ 5 用户接口(命令接口 + 程序接口) │ ← 人怎么用、程序怎么用
└───────────────────────────────────────┘用户接口的两类:
| 接口 | 使用者 | 形式 |
|---|---|---|
| 命令接口 | 用户(人) | 联机(交互式命令,如 shell 命令)、脱机(批处理作业说明书) |
| 程序接口 | 程序(代码) | 系统调用(就是 os/02-syscall.md 的主题) |
⚠️ 易错点:图形用户界面(GUI)不是"第三种接口",它是命令接口的一种实现形式(命令的图形化)。"命令接口 / 程序接口"是二分法。
六、运行机制(软硬交界的关键一节)
1. 两种处理器状态
| 状态 | 别名 | 能执行什么 | 谁在跑 |
|---|---|---|---|
| 内核态(核心态/管态) | supervisor mode | 全部指令(含特权指令) | OS 内核代码 |
| 用户态(目态) | user mode | 只有非特权指令 | 应用程序 |
靠什么区分:程序状态字寄存器(PSW)中的一个模式位。切换状态 = 修改 PSW,而修改 PSW 本身是特权指令——所以用户程序无法自己"越狱"到内核态。
2. 特权指令与非特权指令
| 类别 | 能否在用户态执行 | 例子 |
|---|---|---|
| 特权指令 | 不能 | 关中断/开中断、置时钟、清内存、修改 PSW、I/O 指令、设置中断屏蔽字、修改页表基址寄存器、停机 |
| 非特权指令 | 能 | 算术逻辑运算、取数存数(自己地址空间)、条件转移、系统调用指令(陷阱指令) |
⚠️ 关键:系统调用指令本身必须能在用户态执行——否则用户程序永远无法"请求"内核服务。它是唯一一条"合法的越界门"。
3. 内核的组成
| 组成部分 | 内容 | 是否与硬件直接打交道 |
|---|---|---|
| 时钟管理 | 计时、时间片管理、定时器 | 是 |
| 中断机制 | 中断处理、异常处理(OS 的"心跳") | 是 |
| 原语 | 处于系统最底层、不可被中断的公用小程序(如 锁、唤醒) | 不一定 |
| 进程管理 / 存储器管理 / 设备管理 | 相对高层的功能 | 不一定 |
"原语必须不可中断"的原因:原语常常在修改关键数据结构(如就绪队列),若中途被打断,队列可能处于不一致状态——所以要用"关中断"保护起来。这就是"关中断"成为特权指令的直接原因。
4. 内核结构(只需了解对比)
| 结构 | 特点 | 优点 | 缺点 |
|---|---|---|---|
| 单体内核(宏内核) | 全部功能放在一个内核地址空间里 | 性能高(函数调用,无跨域开销) | 庞大、难维护、一个模块出错可能导致整机崩溃 |
| 微内核 | 只把最基本的功能(进程调度、中断、IPC)留在内核,其余(文件系统、驱动)放到用户态 | 可靠、易扩展、易移植 | 性能差(用户态与内核态频繁切换、消息传递开销大) |
| 层次结构 | 内核分层,每层只调用下一层 | 清晰、易调试 | 层划分困难、越层调用受限 |
| 模块化 | 内核 + 可动态加载的模块 | 灵活 | 模块间可能互相依赖 |
| 外核 | 内核只负责资源分配,不负责抽象 | 灵活 | 应用要自己做很多事 |
现代现实:Windows / Linux 都是"单体内核 + 模块化"(性能优先,兼顾灵活),微内核主要用于对可靠性要求极高的场景(如 QNX)。
示例
例 1:多道批处理到底提升了多少 CPU 利用率
某系统有一个 CPU 和若干台打印机。每个程序的生命周期是"计算 20 ms → 打印 30 ms"(打印期间 CPU 空闲)。分别求以下四种配置下的完成时间与 CPU 利用率:(a)单道,1 台打印机;(b)两道,1 台打印机;(c)两道,2 台打印机;(d)三道,3 台打印机。
完整计算过程:
(a)单道,1 台打印机
程序必须先算完再打印,且打印期间 CPU 空闲:
(b)两道,1 台打印机
CPU 在第 20 ms 算完 P1,接着算 P2(0~20 算 P1、20~40 算 P2);打印机只能服务一个:P1 的打印 20~50,P2 的打印必须等打印机空闲(50)后才能开始,即 50~80。
| 程序 | CPU 占用 | 打印占用 |
|---|---|---|
| P1 | 0 ~ 20 | 20 ~ 50(打印机 1) |
| P2 | 20 ~ 40 | 50 ~ 80(打印机 1) |
(c)两道,2 台打印机
P2 算完后(40 ms)第二台打印机立刻可用:
| 程序 | CPU 占用 | 打印占用 |
|---|---|---|
| P1 | 0 ~ 20 | 20 ~ 50(打印机 1) |
| P2 | 20 ~ 40 | 40 ~ 70(打印机 2) |
(d)三道,3 台打印机
| 程序 | CPU 占用 | 打印占用 |
|---|---|---|
| P1 | 0 ~ 20 | 20 ~ 50(打印机 1) |
| P2 | 20 ~ 40 | 40 ~ 70(打印机 2) |
| P3 | 40 ~ 60 | 60 ~ 90(打印机 3) |
汇总对照:
| 配置 | 完成时间 | CPU 忙 | 利用率 | 相比单道 |
|---|---|---|---|---|
| (a) 单道 / 1 打印机 | 50 ms | 20 ms | 40.00% | 1.00× |
| (b) 两道 / 1 打印机 | 80 ms | 40 ms | 50.00% | 1.25× |
| (c) 两道 / 2 打印机 | 70 ms | 40 ms | 57.14% | 1.43× |
| (d) 三道 / 3 打印机 | 90 ms | 60 ms | 66.67% | 1.67× |
结论:多道确实提高利用率(40% → 66.7%),但提升被"外设数量"封顶——(b) 与 (c) 对比说明加一台打印机比加一道程序更管用(同样两道程序,利用率从 50% 涨到 57.14%)。
这就是"多道批处理"的核心逻辑:让 CPU 与 I/O 并行。程序打印时 CPU 去算别的程序,CPU 不再为等 I/O 而空转。但并行的"宽度"取决于最短缺的那种资源——本例中就是打印机。
例 2:虚拟存储器的代价——缺页有多贵
某机主存访问时间 100 ns,磁盘访问时间 10 ms。若采用虚拟存储器(请求分页),求缺页率为
、 、 、 时的有效访问时间(EAT, Effective Access Time),并与"不缺页"对比。
完整计算过程:
第一步,统一单位(磁盘时间换算成 ns):
第二步,对比两个存储层级的差距:
第三步,EAT 公式(
第四步,逐项计算:
| 缺页率 | EAT 计算 | EAT | 比不缺页慢 |
|---|---|---|---|
| 100 099 ns | 1001 倍 | ||
| 10 099.9 ns | 101 倍 | ||
| 1100 ns | 11 倍 | ||
| 200 ns | 2 倍 |
结论:
- 磁盘比主存慢 5 个数量级——这是"虚拟存储器"这个"欺骗"必须付的代价。
- 缺页率每降一个数量级,EAT 大致也降一个数量级(
的 100 099 ns → 的 10 099.9 ns)。 - 缺页率必须压到
以下(此时只慢 2 倍)才有实用价值——这就是"局部性原理"存在的意义:程序天然倾向于集中在少量页面上,才能把缺页率压到这个量级。
与第 13 篇(虚拟存储器)的口径对齐:那里的 EAT 三项式
还含 TLB 与两级页表项;本篇为了突出"缺页有多贵",把 TLB 与页表项简化为 0。两者不矛盾,区别在于是否把页表查询成本算进去。
例 3:并发与并行的时序对照
两个程序 P1、P2,各需运行 4 个时间单位。分别画出"单核并发"与"双核并行"的时序,并对比完成时间。
单核并发(时间片轮转,每片 1 个时间单位):
时间: 1 2 3 4 5 6 7 8
P1: █ . █ . █ . █ .
P2: . █ . █ . █ . █
↑ 微观上任意时刻只有 1 个在跑(宏观同时)
完成时间 = 8 个单位双核并行:
时间: 1 2 3 4
P1: █ █ █ █
P2: █ █ █ █
↑ 微观上两个真的同时在跑
完成时间 = 4 个单位对比:
| 配置 | 完成时间 | 微观瞬时并发度 | 加速比 |
|---|---|---|---|
| 单核并发 | 8 | 1 | 1.0× |
| 双核并行 | 4 | 2 | 2.0× |
结论:并发不提高"总工作量"的完成速度(单核下总时间还是 8),它提高的是"公平性与响应性"——让两个程序都在推进,用户感觉"都在跑"。只有并行才真正缩短完成时间(4 个单位)。
这也解释了为什么"多核"是性能提升,而"分时"只是"资源共享"。并发解决的是"有没有",并行解决的是"快不快"。
例 4:C 实现——多道批处理的调度模拟
把例 1 的四种配置交给程序算。这里的"调度器"只做两件事:CPU 按到达顺序逐个算、每个程序算完后挑最早空闲的打印机。
#include <stdio.h>
/* 每个程序: 计算 20 ms 然后打印 30 ms */
#define T_CPU 20.0
#define T_DEV 30.0
#define MAX_DEV 8
/* 模拟 n_jobs 道程序、n_dev 台打印机, 输出完成时间与 CPU 利用率 */
static void simulate(int n_jobs, int n_dev, const char *tag) {
double cpu_free = 0.0;
double dev[MAX_DEV];
for (int i = 0; i < n_dev; i++) dev[i] = 0.0;
for (int i = 0; i < n_jobs; i++) {
double cpu_end = cpu_free + T_CPU; /* 本程序算完的时刻 */
cpu_free = cpu_end;
/* 挑最早空闲的打印机 */
int k = 0;
for (int j = 1; j < n_dev; j++)
if (dev[j] < dev[k]) k = j;
/* 打印起点 = max(算完时刻, 打印机空闲时刻) */
double start = (cpu_end > dev[k]) ? cpu_end : dev[k];
dev[k] = start + T_DEV;
}
/* 完成时间 = max(CPU 空闲时刻, 所有打印机空闲时刻) */
double makespan = cpu_free;
for (int i = 0; i < n_dev; i++)
if (dev[i] > makespan) makespan = dev[i];
/* 注意: 不要用 %-18s 给中文补齐 —— printf 按"字节"补, 中文会错位 */
printf("%s: 完成 %.1f ms, CPU 忙 %.1f ms -> 利用率 %.2f%%\n",
tag, makespan, cpu_free, cpu_free / makespan * 100);
}
int main(void) {
simulate(1, 1, "单道(1 程序/1 外设)");
simulate(2, 1, "两道/1 台外设 ");
simulate(2, 2, "两道/2 台外设 ");
simulate(3, 3, "三道/3 台外设 ");
return 0;
}
c 本站为静态站,不提供在线运行;可复制到本地用 gcc / python 执行
预期输出:
单道(1 程序/1 外设): 完成 50.0 ms, CPU 忙 20.0 ms -> 利用率 40.00%
两道/1 台外设 : 完成 80.0 ms, CPU 忙 40.0 ms -> 利用率 50.00%
两道/2 台外设 : 完成 70.0 ms, CPU 忙 40.0 ms -> 利用率 57.14%
三道/3 台外设 : 完成 90.0 ms, CPU 忙 60.0 ms -> 利用率 66.67%三个要点:
printf的宽度对中文是"按字节补齐":%-18s会把每个汉字当 3 字节,中文标签必然错位。所以本例用手工补空格(在"两道/1 台外设 "后面加空格)或干脆不加宽度。这是中文项目里最常见的一个"排版 bug"。- 完成时间必须取
max(CPU 空闲时刻, 所有设备空闲时刻):只取 CPU 空闲时刻会漏掉"最后一个程序的打印还没结束"这种情况。 - 挑设备的规则决定了利用率:本例用"最早空闲"(等价于先进先出)。若改成"随机挑",利用率可能更差——这正是 OS 调度要解决的问题。
例 5:Python——多道利用率与缺页代价验算
import math
# ===== 例 1: 多道批处理 CPU 利用率 =====
def flowshop(n_jobs, n_dev, t_cpu=20.0, t_dev=30.0):
"""CPU 逐个算, 每个作业算完挑最早空闲的设备; 返回 (CPU 忙时长, 完成时间, 明细)"""
cpu_free, free, detail = 0.0, [0.0] * n_dev, []
for i in range(n_jobs):
cpu_end = cpu_free + t_cpu
cpu_free = cpu_end
k = min(range(n_dev), key=lambda j: free[j]) # 最早空闲的设备
start = max(cpu_end, free[k])
free[k] = start + t_dev
detail.append((i + 1, cpu_free - t_cpu, cpu_end, start, start + t_dev, k + 1))
return cpu_free, max(max(free), cpu_free), detail
print('=== 例 1: 每个程序 计算 20 ms + 打印 30 ms ===')
for tag, nj, nd in [('单道 / 1 打印机 ', 1, 1), ('两道 / 1 打印机 ', 2, 1),
('两道 / 2 打印机 ', 2, 2), ('三道 / 3 打印机 ', 3, 3)]:
cpu, mk, detail = flowshop(nj, nd)
print(' %s 完成 %5.1f ms, CPU 忙 %5.1f ms -> 利用率 %6.2f%%'
% (tag, mk, cpu, cpu / mk * 100))
for i, c0, c1, d0, d1, dev in flowshop(2, 2)[2]:
print(' P%d: CPU %2.0f-%2.0f, 打印 %2.0f-%2.0f (打印机 %d)' % (i, c0, c1, d0, d1, dev))
print(' 结论: 加一台打印机 (两道 1 -> 2 台) 让利用率 50.00% -> 57.14%')
print(' 加一道程序 (两道 2 台 -> 三道 3 台) 让利用率 57.14% -> 66.67%')
# ===== 例 2: 缺页代价 =====
print('\n=== 例 2: 主存 100 ns vs 磁盘 10 ms ===')
disk_ns = 10 * 1e6
print(' 磁盘/主存 = %.0f 倍 = %.0f 个数量级'
% (disk_ns / 100, math.log10(disk_ns / 100)))
for p in [1e-2, 1e-3, 1e-4, 1e-5]:
eat = (1 - p) * 100 + p * disk_ns
print(' 缺页率 %.0e -> EAT = %9.1f ns (比不缺页慢 %.0f 倍)' % (p, eat, eat / 100))
print(' 结论: 缺页率每降一个数量级, EAT 大致也降一个数量级')
print(' 必须压到 1e-5 以下 (只慢 2 倍) 才有实用价值 -> 靠局部性原理')
# ===== 例 3: 并发 vs 并行 =====
print('\n=== 例 3: 两个程序各需 4 个单位 ===')
print(' 单核并发(时间片轮转) -> 完成 8 个单位, 瞬时并发度 1')
print(' 双核并行 -> 完成 4 个单位, 瞬时并发度 2, 加速比 2.0x')
print(' 并发提高 "公平/响应", 并行才真正提高 "速度"')
# ===== 四大特征的自检 =====
print('\n=== 四大特征自检 ===')
for name, text in [
('并发', '同一"时间段"内多个程序交替运行; 单核即可, 宏观同时微观串行'),
('共享', '资源供多个并发进程共同使用; 分互斥共享与同时共享'),
('虚拟', '一个物理实体变多个逻辑对应物; 时分复用(虚拟处理器) / 空分复用(虚拟存储器)'),
('异步', '进程走走停停、速度不可预知; 是并发的必然结果'),
]:
print(' %s: %s' % (name, text))
print(' 并发 <-> 共享 互为存在条件: 没有并发无所谓共享; 不能共享并发就进行不下去')
python 本站为静态站,不提供在线运行;可复制到本地用 gcc / python 执行
输出对照:例 1 得四种配置的利用率为 40.00% / 50.00% / 57.14% / 66.67%,与手算一致;例 2 得磁盘比主存慢 100000 倍(5 个数量级),
考点
考点
1. 必背结论
- OS 的四大特征:并发、共享、虚拟、异步。其中并发与共享互为存在条件;异步是并发的必然结果。
- 并发 = 宏观同时、微观串行(单核即可);并行 = 同一时刻真的同时(必须多核)。
- 共享两型:互斥共享(打印机)、同时共享(磁盘文件)。
- 虚拟两型:时分复用(虚拟处理器、虚拟设备)、空分复用(虚拟存储器)。
- OS 五大功能:处理机管理、存储器管理、文件管理、设备管理、用户接口。
- 用户接口两分:命令接口(联机/脱机)与程序接口(系统调用)。GUI 不算第三种。
- 两态靠 PSW 的模式位区分;修改 PSW 是特权指令,用户程序无法自行进入内核态。
- 内核组成:时钟管理、中断机制、原语(不可中断)+ 进程/存储/设备管理。
- 内核结构:单体内核(性能高、易崩溃)、微内核(可靠、性能差)、层次、模块化、外核。Windows / Linux 是"单体内核 + 模块化"。
- 多道批处理的三大代价:平均周转时间长、无交互能力、调度复杂。
2. 高频陷阱
- 把"并发"当"并行":单核也能并发(分时交替),但不能并行。这是本考点第一大失分点。
- 说"并发一定提升性能":错。并发提升的是公平性与响应性(例 3 里单核并发仍是 8 个单位);只有并行才缩短完成时间。
- 说"没有共享,并发也能进行":错。并发与共享互为存在条件——这是书本上的原话,考概念题必答。
- 把"异步"理解成"随机/乱序执行":异步指进程推进速度不可预知(走走停停),不是"指令乱序"。
- 把 GUI 当"第三种用户接口":错。GUI 是命令接口的图形化实现,用户接口只有"命令接口 + 程序接口"两类。
- 把"原语"当普通函数:原语必须不可中断(关中断保护),这是它区别于普通函数的唯一要点。
- 忘了"修改 PSW 是特权指令":这一条是"用户程序无法自行提权"的根本原因,概念题常考。
- 把"微内核性能差"的原因答成"功能少":错。原因是用户态与内核态频繁切换 + 消息传递开销——功能少反而更安全,不是更慢的原因。
- 多道批处理的"利用率提高"答成"响应变快":恰恰相反,多道批处理没有交互、响应慢。它提高的只是资源利用率与吞吐量。
- 说"只要加程序就能继续提利用率":错。例 1 显示提升被外设数量封顶——(b) 加一台打印机 (50% → 57.14%) 的效果比加程序更直接。
3. 解题模板("多道程序利用率题")
① 列出每个作业的"资源序列": 先 CPU x ms, 再外设 y ms
② 按到达顺序排 CPU 占用时间轴 (CPU 同一时刻只能服务一个)
③ 每个作业算完后, 挑"最早空闲"的那台外设接上
起点 = max(作业算完时刻, 设备空闲时刻)
④ 完成时间 = max(CPU 时间轴末端, 所有设备时间轴末端)
⑤ 利用率 = 总 CPU 忙时间 / 完成时间
⑥ 若问"还能不能提高": 看瓶颈是哪类资源
设备数不足 -> 加设备比加程序有效4. 与相邻章节的接口
- 第 13 篇(虚拟存储器):"虚拟"这个 OS 特征在硬件上的落地就是虚拟存储器;本篇例 2 的缺页代价(5 个数量级)正是它必须靠"局部性原理"才能成立的原因。
- 第 33 篇(异常与中断):中断是 OS 的"心跳"——时钟中断驱动调度、I/O 中断唤醒进程、
syscall用自陷进入内核。"中断机制"是内核的四大组成之一,就在本篇第六节。 - 第 41 篇(I/O 系统):多道批处理"CPU 与 I/O 并行"的硬件基础就是中断与 DMA——没有它们,CPU 只能空等设备(程序查询方式)。
- 第 20~30 篇(指令系统 / CPU):特权指令与非特权指令的划分直接来自硬件的"两态"设计;PSW 的模式位就是第 33 篇里"中断响应时保存现场"要保存的那个东西。
- 下一章
os/02-syscall.md:"用户接口"里的"程序接口"就是系统调用;本篇讲清了"为什么需要两态",下一篇讲"怎么从用户态合法地进内核态"。
小结
- 操作系统 = 管理者 + 服务员 + 扩展机器,两个核心问题:"一台机器怎么变成很多台机器"、"怎么让硬件同时服务很多人"。
- 四大特征:并发(宏观同时、微观串行)、共享(互斥/同时)、虚拟(时分/空分复用)、异步(走走停停)。并发与共享互为存在条件,异步是并发的必然结果。
- 并发 ≠ 并行:单核也能并发(例 3 里仍是 8 个单位),只有多核才真正缩短完成时间(4 个单位,2.0×)。
- 两态靠 PSW 模式位区分,修改 PSW 是特权指令——用户程序无法自行提权;系统调用指令本身是非特权的(唯一合法越界门)。
- 多道批处理提高利用率但被外设封顶:例 1 里 40% → 66.67%,加一台打印机的效果比加一道程序更明显。
- 虚拟存储器是"空分复用"的落地,代价是缺页:例 2 里磁盘比主存慢 5 个数量级,缺页率必须压到
以下才只慢 2 倍——靠局部性原理。
下一篇:系统调用:用户态与内核态
评论(0)
当前浏览器不允许本地存储,评论无法保存。
还没有评论,来说两句。