操作系统知识完全总结(11章全)
📚 操作系统知识完全总结(11章全)
本文基于 11 章操作系统教材编写,面向零基础学习者。
每个知识点配有通俗解释 + 生活类比 + 举例说明。
目录
- [第 1 章 操作系统引论]
- [第 2 章 进程和线程]
- [第 3 章 调度]
- [第 4 章 存储管理]
- [第 5 章 文件系统]
- [第 6 章 输入输出管理]
- [第 7 章 用户接口服务]
- [第 8 章 死锁]
- [第 9 章 嵌入式操作系统]
- [第 10 章 分布式系统和云计算]
- [第 11 章 安全与保护机制]
第 1 章 操作系统引论
1.1 什么是操作系统?
通俗理解: 操作系统(OS)是电脑的"大管家"——它管理所有硬件(CPU、内存、硬盘等),同时为应用程序(微信、浏览器等)提供运行环境。
核心定义: 操作系统是控制和管理计算机硬件与软件资源的系统软件。
生活中的类比:
想象一个餐厅:操作系统就是餐厅经理,硬件(CPU、内存等)是厨房设备,应用程序(App)是厨师和服务员。经理不直接做菜,但协调一切——分配炉灶、安排人员、确保不冲突。
1.2 操作系统的四大角色
| 角色 | 通俗解释 | 例子 |
|---|---|---|
| 资源管理者 | 管理 CPU、内存、硬盘等硬件资源 | 决定哪个程序先用 CPU |
| 用户接口 | 提供人与计算机交互的方式 | 鼠标点击、键盘输入、触屏 |
| 程序执行环境 | 让应用程序能在计算机上运行 | 你打开 Word 时,OS 帮它分配内存 |
| 服务提供者 | 提供文件读写、网络通信等功能 | 保存文件、发送网络请求 |
1.3 操作系统的发展历史
第一代 (1940s-1950s):无操作系统 → 插拔线路、纸带输入
↓
第二代 (1950s-1960s):批处理系统 → 一次提交一批任务
↓
第三代 (1960s-1970s):多道程序系统 → 内存中同时有多道程序
↓
第四代 (1980s至今):分时/个人计算机 → Windows, UNIX, Linux, macOS
↓
现代:移动/嵌入式/分布式/云操作系统
1.4 操作系统的分类
| 类型 | 特点 | 例子 |
|---|---|---|
| 批处理系统 | 批量执行任务,用户无法交互 | 早期 IBM 大型机 |
| 分时系统 | 多用户同时使用,轮流分配时间片 | UNIX、Linux |
| 实时系统 | 必须在严格时限内响应 | 飞机自动驾驶、导弹控制 |
| 个人系统 | 单用户使用,交互性强 | Windows、macOS |
| 网络系统 | 面向网络环境,管理网络资源 | Windows Server |
| 分布式系统 | 多台计算机协同工作 | Google 搜索系统 |
| 嵌入式系统 | 内置在设备中,专用性强 | 手机、智能手表、路由器 |
✨ 小贴士: 我们日常用的 Windows/macOS 是个人操作系统 + 分时系统的结合体。手机系统(iOS/Android)本质上属于嵌入式操作系统。
1.5 操作系统的核心功能
- 进程管理 — 管理正在运行的程序
- 存储管理 — 分配和回收内存
- 文件管理 — 管理硬盘上的文件和目录
- 设备管理 — 管理键盘、鼠标、打印机等设备
- 用户接口 — 提供图形界面或命令行
1.6 操作系统的结构
(1)简单结构(单体内核)
- 所有功能都放在内核中
- 例子:MS-DOS、早期 UNIX
- 优点:效率高
- 缺点:一个模块崩溃,整个系统崩溃
(2)分层结构
- 操作系统按层次划分,每层只与相邻层交互
- 优点:易于维护和调试
- 例子:THE 操作系统
(3)微内核结构
- 内核只保留最基本的功能(进程通信、基本调度)
- 其他功能(文件系统、设备驱动)在用户空间运行
- 优点:稳定性高、扩展性好
- 例子:Minix、QNX
(4)模块化结构
- 内核可以动态加载和卸载模块
- 现代 Linux 使用此结构
(5)虚拟机结构
- VMM(虚拟机监视器)在硬件之上运行,创建多个虚拟机
- 例子:VMware、VirtualBox、KVM
第 2 章 进程和线程
2.1 进程的概念
通俗理解: 进程就是"正在执行的程序"。
程序是静态的(像一个菜谱),进程是动态的(像正在照着菜谱做菜的过程)。
举例:
- 双击打开微信 → 微信程序变成一个"进程"
- 同时打开浏览器、Word、微信 → 三个进程在同时运行
2.2 进程的三态模型
┌──────────┐
│ 就绪态 │ ◄────────────┐
└────┬─────┘ │
│ (调度选中) │ (I/O 完成/事件发生)
▼ │
┌──────────┐ I/O请求 ┌──────────┐
│ 运行态 │ ──────────► │ 阻塞态 │
└──────────┘ └──────────┘
│
│ (时间片用完)
▼
┌──────────┐
│ 就绪态 │
└──────────┘
三种基本状态:
| 状态 | 通俗解释 | CPU | 能否继续执行 |
|---|---|---|---|
| 运行态(Running) | 正在使用 CPU | 有 | ✓ |
| 就绪态(Ready) | 万事俱备,只等 CPU | 无 | 等 CPU 分配 |
| 阻塞态(Blocked/Wait) | 在等某件事完成 | 无 | ✗ (等事件完成) |
生活的类比: 去银行办事
- 运行态:你正在柜台办理
- 就绪态:你在排队等着,轮到你了就上
- 阻塞态:需要填表但笔没墨水了,只能等着
五种状态模型(扩展):
┌───────┐
│ 新建态 │ ← 进程被创建
└───┬───┘
▼
┌───────┐ ┌──────────┐
│ 就绪态 │ ◄───► │ 运行态 │
└───┬───┘ └────┬─────┘
│ │
▼ ▼
┌───────┐ ┌──────────┐
│ 阻塞态 │ │ 终止态 │
└───────┘ └──────────┘
2.3 进程控制块(PCB)
核心概念: 操作系统为每个进程建立一个 PCB,就像每个人的"身份证"。
PCB 中记录了哪些信息?
| 信息类型 | 内容 |
|---|---|
| 进程标识 | PID(进程ID)、PPID(父进程ID)、UID(用户ID) |
| 处理机状态 | 寄存器值、程序计数器(PC)、状态字 |
| 进程调度信息 | 状态、优先级、等待时间 |
| 内存管理信息 | 页表/段表指针 |
| 资源清单 | 打开的文件列表、使用设备信息 |
PCB 的组织方式:
- 链表方式 — 按状态将 PCB 连成不同链表(就绪队列、阻塞队列等)
- 索引方式 — 建立索引表
2.4 进程的上下文切换
概念: CPU 从一个进程切换到另一个进程的过程。
切换步骤:
- 保存当前进程的上下文(寄存器、程序计数器等)
- 更新 PCB
- 选择新进程
- 恢复新进程的上下文
- 执行新进程
上下文切换是有代价的(需要时间),所以不是切换得越频繁越好。
2.5 进程的创建和终止
创建原因:
- 系统初始化
- 用户请求(双击运行程序)
- 正在运行的进程创建子进程(如 Chrome 创建新标签页)
- 批处理作业启动
终止原因:
- 正常完成
- 发生错误
- 被其他进程终止
UNIX/Linux 中的 fork():
#include <unistd.h>
#include <stdio.h>
int main() {
pid_t pid = fork(); // 创建子进程
if (pid < 0) {
fprintf(stderr, "Fork Failed");
return 1;
}
else if (pid == 0) {
// 子进程代码
execlp("/bin/ls", "ls", NULL);
}
else {
// 父进程代码
wait(NULL); // 等待子进程完成
printf("Child Complete");
}
return 0;
}
fork()一次调用,两次返回——父进程返回子进程 PID,子进程返回 0。
2.6 进程间通信(IPC)
| 方式 | 通俗解释 | 特点 |
|---|---|---|
| 管道(Pipe) | 一个进程写,另一个读 | 单向、一般适用于父子进程 |
| 消息队列 | 进程发送/接收消息 | 双向、无需同步 |
| 共享内存 | 多个进程共享一块内存 | 速度最快,需同步机制 |
| 信号量 | 像红绿灯控制访问 | 用于同步,不是传数据 |
| 套接字(Socket) | 网络通信 | 可跨机器通信 |
💡 生活类比:
- 管道 = 两个人传纸条
- 消息队列 = 互相写信
- 共享内存 = 共用一块白板
- 信号量 = 红绿灯
- Socket = 打电话
2.7 线程的概念
通俗理解: 线程是进程中的"子任务"。
进程 = 工厂,线程 = 工厂里的工人
进程与线程的区别
| 对比项 | 进程 | 线程 |
|---|---|---|
| 资源开销 | 大(独立内存空间) | 小(共享进程内存) |
| 切换速度 | 慢(需要切换地址空间) | 快(共享地址空间) |
| 通信方式 | IPC(较复杂) | 直接读写共享数据 |
| 独立性 | 一个崩溃不影响其他进程 | 一个崩溃可能影响同进程所有线程 |
举例: 打开浏览器是一个进程,内部有多个线程:
- 线程 1:渲染页面
- 线程 2:下载图片
- 线程 3:响应用户点击
用户级线程 vs 内核级线程
| 对比 | 用户级线程 | 内核级线程 |
|---|---|---|
| 管理方式 | 用户空间管理 | 操作系统管理 |
| 切换速度 | 快(无需系统调用) | 慢(需要陷入内核) |
| 阻塞影响 | 一个线程阻塞→整个进程阻塞 | 一个线程阻塞不影响其他线程 |
| 并行性 | 不能利用多核 | 能利用多核 |
2.8 多线程模型
多对一模型: 多个用户线程映射到一个内核线程
- 不能利用多核
一对一模型: 每个用户线程映射到一个内核线程
- 能利用多核,但创建线程成本高
多对多模型: 多个用户线程映射到多个内核线程
- 结合了两者的优点
第 3 章 调度
3.1 什么是调度?
通俗理解: 当多个进程都想使用 CPU 时,操作系统得决定"谁先用、用多久"——这就是调度。
就像一家人排队用一台电脑——操作系统像排班表,决定每个人用多久、谁先用。
3.2 调度的层次
| 层次 | 名称 | 作用 | 频率 |
|---|---|---|---|
| 高级调度(长程) | 作业调度 | 哪些作业进入内存 | 慢(秒/分钟级) |
| 中级调度(中程) | 交换调度 | 进程在内存与磁盘间交换 | 中等 |
| 低级调度(短程) | CPU 调度 | 哪个进程使用 CPU | 极快(毫秒级) |
3.3 调度的目标
- 公平性 — 每个进程都能得到 CPU 时间
- 响应时间短 — 交互式操作反馈快
- 吞吐量大 — 单位时间完成的任务多
- CPU 利用率高 — CPU 不闲置
- 平衡资源 — 让系统中的各类资源都能被有效利用
3.4 调度方式
非抢占式(Non-preemptive): 进程一旦获得 CPU,除非主动放弃,否则一直运行。
- 适合:批处理系统
抢占式(Preemptive): 操作系统可以强制暂停正在运行的进程,把 CPU 分配给其他进程。
- 适合:分时系统、实时系统
3.5 关键性能指标
周转时间 = 进程完成时间 - 进程到达时间
等待时间 = 在就绪队列中等待的总时间
响应时间 = 提交请求到第一次响应的时间
CPU利用率 = CPU 忙的时间 / 总时间
吞吐量 = 单位时间完成的进程数
3.6 常见的调度算法
(1)先来先服务(FCFS)
原理: 谁先到达谁先用(像银行排队)。
| 优点 | 缺点 |
|---|---|
| 简单、公平 | 短任务可能被长任务阻塞 |
| 容易实现 | 不适合交互式系统 |
举例:
进程 A(需要 10 分钟)先到,进程 B(需要 1 分钟)后到
→ A 执行 10 分钟,B 再执行 1 分钟
→ 平均等待时间 = (0 + 10) / 2 = 5 分钟
→ B 只需要 1 分钟,却等了 10 分钟!不合理。
(2)短作业优先(SJF)
原理: 先执行需要时间最短的任务。
| 优点 | 缺点 |
|---|---|
| 平均等待时间最小(理论上最优) | 长任务可能"饿死" |
| 适合批处理系统 | 需要预先知道运行时间 |
举例:
进程:A(6ms)、B(3ms)、C(1ms)
SJF 顺序:C(1ms) → B(3ms) → A(6ms)
平均等待时间 = (0 + 1 + 4) / 3 ≈ 1.67ms ✅(远优于 FCFS)
(3)最短剩余时间优先(SRTN)
- SJF 的抢占式版本
- 每次有新进程到达时,比较剩余时间,选最短的继续
- 适用于交互式环境
(4)时间片轮转(Round Robin)
原理: 每个进程轮流使用 CPU,每次用固定时间(时间片)。
关键参数: 时间片大小
- 时间片太大 → 退化为 FCFS
- 时间片太小 → 上下文切换开销太大
举例:
时间片 = 4ms,进程到达顺序:A(6ms)、B(3ms)、C(1ms)
执行顺序:A(4ms) → B(3ms) → C(1ms) → A(2ms)
响应时间:A=0, B=4, C=7(都很快得到响应 ✅)
(5)优先级调度
原理: 每个进程分配优先级,优先级高的先执行。
静态优先级: 创建时确定,不变
动态优先级: 随进程行为变化(如等待越久优先级越高,防止"饥饿")
(6)多级反馈队列
原理: 设置多个就绪队列,各队列使用不同调度策略和优先级。
┌────────────────┐
┌──────────────────►│ 队列1(优先级最高)│◄── 时间片 = 8ms
│ └───────┬────────┘
│ 未完成 │
│ ┌──────▼────────┐
│──────────────────►│ 队列2 │◄── 时间片 = 16ms
│ 未完成 └───────┬────────┘
│ │
│ ┌──────▼────────┐
└──────────────────►│ 队列3(最低) │◄── FCFS
└────────────────┘
这是现代操作系统最常用的调度算法(Windows、Linux 都在用)!
3.7 作业调度(JCB)
作业控制块(JCB) — 记录作业信息的结构,类似进程的 PCB。
作业调度算法:
- 先来先服务
- 短作业优先
- 优先级调度
3.8 UNIX/Linux 调度
- Linux 使用 完全公平调度器(CFS)
- 基于优先级 + 运行时间动态调整
- 确保所有进程公平使用 CPU
第 4 章 存储管理
4.1 存储管理概述
核心问题: 内存有限(比如 8GB),但多个程序都想用,怎么分配?
四个主要目标:
- 内存分配 — 给进程分配内存空间
- 地址转换 — 把程序中的逻辑地址转为物理地址
- 内存保护 — 一个进程不能访问另一个进程的内存
- 内存扩充 — 让有限的内存运行更大的程序
💡 类比: 存储管理像图书馆管理——分配书架、找书、防止书被乱拿、用电子书架扩充容量。
4.2 地址的概念
| 地址类型 | 定义 | 通俗理解 |
|---|---|---|
| 物理地址 | 内存中真实的物理单元编号 | 真实的门牌号 |
| 逻辑地址(虚拟地址) | 程序中使用的地址 | 虚构的门牌号 |
程序看到的地址是"假"的,操作系统负责把假地址转成真地址。
4.3 地址绑定(Binding)
发生在不同阶段的地址绑定:
| 阶段 | 绑定方式 | 特点 |
|---|---|---|
| 编译时 | 绝对地址 | 起始地址已知,否则要重新编译 |
| 加载时 | 可重定位地址 | 加载时修改地址 |
| 运行时 | 动态地址映射 | 运行时通过硬件转换(最灵活) |
4.4 内存分配方式
4.4.1 连续分配
固定分区:
- 内存预先分成固定大小的区域
- 简单但浪费(内部碎片)
动态分区:
- 按需分配内存大小
- 容易出现外部碎片
碎片问题:
外部碎片:像停车场停了很多小车,剩下很多小空位——加起来很大,但停不了一辆大车。
四种分区分配算法:
| 算法 | 策略 | 特点 |
|---|---|---|
| 首次适应(First-fit) | 找第一个够用的分区 | 速度最快 |
| 最佳适应(Best-fit) | 找刚刚够用的分区 | 减少大块浪费 |
| 邻近适应(Next-fit) | 从上一次找到的位置开始找 | 分配更均匀 |
| 最差适应(Worst-fit) | 找最大的分区 | 留下较均匀的空隙 |
4.4.2 非连续分配——分页
核心思想: 把内存分成固定大小的"页框"(通常 4KB),程序的虚拟空间也分成同样大小的"页"。
关键概念:
- 页(Page) — 程序中的固定大小块(虚拟空间)
- 页框/帧(Frame) — 内存中的固定大小块(物理空间)
- 页表(Page Table) — 记录页→页框的映射关系
- TLB(快表/转换后备缓冲器) — 页表的"硬件缓存",加速地址转换
虚拟地址结构(假设 32 位,4KB 页):
┌──────────────┬─────────────┐
│ 页码 p │ 页内偏移 d │
│ (20位) │ (12位) │
└──────────────┴─────────────┘
地址转换过程:
逻辑地址 A → p = INT(A/L), d = A MOD L
→ 查页表得到页框号 f
→ 物理地址 = f × L + d
💡 类比: 就像查字典——页码(页号)告诉你在哪块区域,具体第几个字(偏移)是具体位置。
TLB 加速:
- 有 TLB 时:
20ns(TLB查询) + 100ns(内存访问) = 120ns - 无 TLB 时:
100ns(查页表) + 100ns(内存访问) = 200ns - TLB 命中率 ≥ 98% → 性能提升显著
4.4.3 分段存储管理
思路: 按程序的逻辑结构分段:代码段、数据段、堆栈段等。
虚拟地址结构: 段号 + 段内偏移
段表: 记录每段的基地址和段长
与分页的对比:
| 对比 | 分页 | 分段 |
|---|---|---|
| 划分依据 | 固定大小(硬件决定) | 逻辑结构(用户可见) |
| 大小 | 固定(如 4KB) | 可变 |
| 优点 | 无外部碎片 | 符合程序逻辑,便于共享和保护 |
4.4.4 段页式存储管理
结合分页和分段: 先分段 → 每段再分页
- 分段对用户友好(按逻辑划分)
- 分页对系统友好(避免外部碎片)
- 代价:地址转换需要两次查表
4.5 虚拟内存(超级重要!)
通俗理解: 让程序"以为"自己有超大的内存,实际上部分数据在硬盘上。
就像你在一张桌子上看书,书的内容远远超过桌子大小。你只把当前看的几页放在桌上,其他页放在抽屉里。想看下一页时,从抽屉取出,放回不需要的页。这就是虚拟内存!
工作原理
┌──────────────────┐
│ 虚拟地址空间 │ 程序认为它有超大内存
│ (比如 4GB) │
└────────┬─────────┘
│
▼ 地址转换(分页)
┌────┴────┐
│ 在内存吗? │
└────┬────┘
是↙ ↘否
继续 缺页中断
→ 从硬盘加载页到内存
→ 如果内存满,先换出一些页
→ 更新页表
→ 继续执行
请求分页
程序访问的页不在内存中时发生缺页中断(Page Fault)。
处理流程:
- CPU 捕获缺页异常
- 操作系统找到需要加载的页在硬盘的位置
- 如果内存有空闲 → 直接从硬盘读入
- 如果内存已满 → 先执行页面置换
- 更新页表
- 重新执行导致缺页的指令
页面置换算法
| 算法 | 策略 | 特点 |
|---|---|---|
| FIFO | 先进先出 | 简单但可能换出常用页(Belady异常) |
| LRU(最近最少使用) | 换出最久没有访问的页 | 效果好,实现成本高 |
| Clock(时钟) | 近似 LRU | 硬件支持较少,常用 |
| 最佳置换(OPT) | 换出未来最久不用的页 | 理论最优,无法实现 |
页框分配策略
- 固定分配 — 每个进程分配固定数量的页框
- 可变分配 — 根据进程需求动态调整页框数量
全局置换 vs 局部置换:
- 全局置换 — 缺页时从所有进程中选择换出页
- 局部置换 — 缺页时只从自己的进程中换出
抖动(Thrashing)
现象: 进程频繁缺页,大部分时间花在换入换出上,CPU 利用率极低。
原因: 进程没有获得足够的页框(工作集太大)。
解决方案:
- 工作集模型(保证每个进程有足够的页框)
- 控制多道程序度(不让太多进程同时跑)
内存映射文件
概念: 将文件直接映射到进程的虚拟地址空间,像访问内存一样访问文件。
优点: 简化文件操作,多个进程可以共享映射。
4.6 内核内存分配
- 伙伴系统(Buddy System) — 分配 2 的幂次大小的内存块
- slab 分配器 — 为内核对象创建专用缓存(Linux 使用)
4.7 Linux 内存管理特点
- 使用三级/四级页表(适应 64 位)
- 支持交换(swap)
- OOM Killer — 内存耗尽时自动杀死进程
- 使用 MMU(内存管理单元) 进行硬件地址转换
第 5 章 文件系统
5.1 什么是文件和文件系统
通俗理解: 文件系统是操作系统的"档案柜管理方法"。
| 概念 | 定义 | 类比 |
|---|---|---|
| 文件(File) | 相关信息的集合,存储在硬盘上 | 一本书 |
| 文件系统(File System) | 管理文件的一套机制 | 图书馆分类体系 |
5.2 文件的属性
| 属性 | 说明 | 例子 |
|---|---|---|
| 文件名 | 用户标识文件 | report.docx |
| 标识符 | 系统内部唯一编号(如 i-node) | 345678 |
| 类型 | 文件的种类 | 文本、可执行、图片 |
| 位置 | 在设备上的物理位置 | 扇区号 |
| 大小 | 文件占用空间 | 1024 字节 |
| 保护信息 | 谁可以读/写/执行 | rwxr-xr-- |
| 时间戳 | 创建、修改、访问时间 | 2024-01-15 10:30 |
5.3 文件类型
按用途分类:
| 类别 | 扩展名 |
|---|---|
| 可执行文件 | .exe, .com, .bin, .out |
| 目标文件 | .o, .obj |
| 源程序 | .c, .java, .py, .asm |
| 批处理/脚本 | .bat, .sh, .bash |
| 文本文件 | .txt, .doc, .tex, .rtf |
| 库文件 | .lib, .a, .so, .dll |
| 多媒体 | .jpg, .png, .mp3, .mp4 |
| 归档/压缩 | .zip, .tar, .rar |
按内部结构分类:
- 无结构文件 — 字节流(如 UNIX 普通文件)
- 记录文件 — 由固定或可变长度的记录组成
- 索引文件 — 带有索引以便快速访问
5.4 文件的操作
基本操作:
create(创建) → open(打开) → read/write(读写)
→ seek(定位) → close(关闭) → delete(删除)
其他操作:
append(追加写入)rename(重命名)get_attributes(获取属性)/set_attributes(设置属性)
5.5 文件的逻辑结构
| 结构 | 特点 | 例子 |
|---|---|---|
| 有结构文件 | 由记录组成 | 数据库文件 |
| 无结构文件 | 字节流 | 普通文本文件 |
| 堆结构 | 按到达顺序 | 日志文件 |
| 顺序结构 | 按关键字段排序 | 电话簿 |
| 索引结构 | 带索引表 | 字典 |
5.6 文件目录
5.6.1 文件控制块(FCB)
FCB(File Control Block) — 每个文件的"身份证",包含文件的所有信息。
UNIX 中的 i-node(索引节点):
- 文件名存在目录中,文件信息存在 i-node 中
- i-node 包含文件属性和数据块指针
- 目录项:
文件名 + i-node 号
FCB 包含的内容:
- 文件名
- 文件类型
- 文件大小
- 文件位置(硬盘物理地址)
- 权限信息
- 时间戳
- 所属用户/组
5.6.2 目录结构的发展
① 单级目录
┌─────────────┐
│ 文件A 文件B │ ← 所有文件都在同一层
│ 文件C 文件D │
└─────────────┘
❌ 不能重名、组织混乱
② 二级目录
┌───────────────┐
│ 用户1目录 用户2│
│ ┌─────┐ ┌───┐ │
│ │A B C│ │A D│ │ ← 不同用户目录可以重名
│ └─────┘ └───┘ │
└───────────────┘
③ 树形目录(最常用 ✓)
/ (根目录)
├── usr/
│ ├── bin/
│ ├── lib/
│ └── local/
├── home/
│ ├── user1/
│ │ ├── file1.txt
│ │ └── file2.txt
│ └── user2/
└── etc/
路径类型:
- 绝对路径:从根开始
/home/user1/file.txt - 相对路径:从当前目录开始
./file.txt或../data/file.txt
Windows 用反斜杠
\,UNIX/Linux 用正斜杠/。
5.6.3 目录的操作
create/detele— 创建/删除目录opendir/closedir— 打开/关闭目录readdir— 读取目录项rename— 重命名link/unlink— 链接/取消链接
5.6.4 文件共享
硬链接(Hard Link): 多个目录项指向同一个 i-node
- 删除一个不影响其他
- 不能跨文件系统
软链接/符号链接(Symbolic Link): 一个特殊文件指向另一个文件的路径
- 类似 Windows 的快捷方式
- 可以跨文件系统
5.7 文件的物理结构
| 组织方式 | 工作原理 | 优点 | 缺点 |
|---|---|---|---|
| 连续分配 | 文件存储在连续的块 | 读取快 | 碎片多、扩展难 |
| 链接分配 | 每个数据块指向下一个 | 无外部碎片 | 随机访问慢 |
| 索引分配 | 索引块记录所有数据块位置 | 随机访问快 | 小文件浪费 |
| UNIX 混合索引 | 多级索引结合直接/间接块 | 兼顾大小文件 | 实现复杂 |
UNIX 混合索引(经典的 i-node 结构):
i-node
├── 10 个直接块指针 → 文件 ≤ 40KB(4KB/块)
├── 1 个一级间接块指针 → 可访问 256 个块
├── 1 个二级间接块指针 → 可访问 256² 个块
└── 1 个三级间接块指针 → 可访问 256³ 个块
5.8 空闲空间管理
| 方法 | 说明 |
|---|---|
| 位图(Bitmap) | 每位表示一个块是否空闲 |
| 空闲链表 | 把空闲块链接起来 |
| 成组链接法 | UNIX 使用,组合块和索引 |
5.9 文件系统的可靠性
备份策略:
- 全量备份
- 增量备份(只备份修改的文件)
- 差异备份
日志文件系统(Journaling):
- 写操作先记录到日志
- 崩溃后可通过日志恢复
- 例子:NTFS、ext3/ext4
5.10 常见文件系统
| 文件系统 | 平台 | 特点 |
|---|---|---|
| FAT32 | Windows | 简单、兼容性好,不支持 ≥4GB 文件 |
| NTFS | Windows | 支持大文件、权限、加密、日志 |
| ext4 | Linux | 日志文件系统,性能好 |
| APFS | macOS | 优化 SSD,快照功能 |
| ZFS | Solaris/Linux | 超大容量,数据完整性 |
第 6 章 输入输出管理
6.1 I/O 设备概述
I/O 设备 — 计算机与外界交互的硬件设备(键盘、鼠标、硬盘、打印机等)。
6.1.1 设备分类
按传输速度:
| 级别 | 速度 | 例子 |
|---|---|---|
| 低速 | ≤ 1000 字节/秒 | 键盘、鼠标 |
| 中速 | 1000~1000000 字节/秒 | 打印机、扫描仪 |
| 高速 | ≥ 1MB/秒 | 磁盘、显示器、网卡 |
按传输单位:
| 类型 | 特点 | 例子 |
|---|---|---|
| 块设备(Block Device) | 以数据块为单位,可寻址 | 硬盘、U盘、SSD |
| 字符设备(Character Device) | 以字符流为单位,不可寻址 | 键盘、打印机、鼠标 |
6.1.2 磁盘的基本结构
┌──────┐
磁头 │ 扇区 │ ← 最小的存储单位(512B~4KB)
↓ ├──────┤
┌────┐ │ │
│ 磁道│← 同心圆环 │ 磁道 │
│ │ │ │
│ 柱面│← 所有盘面 └──────┘
│ │ 同一磁道 扇区
└────┘
磁盘访问时间 = 寻道时间 + 旋转延迟 + 传输时间
- 寻道时间:磁头移动到目标磁道的时间(主要时间消耗)
- 旋转延迟:目标扇区旋转到磁头下方的时间
- 传输时间:读取数据的时间
6.1.3 磁盘调度算法
| 算法 | 策略 | 特点 |
|---|---|---|
| FCFS(先来先服务) | 按请求顺序 | 简单,但寻道时间长 |
| SSTF(最短寻道时间优先) | 选最近的请求 | 响应快,但可能"饥饿" |
| SCAN(电梯算法) | 沿一个方向扫描到头再折返 | 公平性好 |
| C-SCAN(循环扫描) | 单向扫描,快速返回起点 | 等待时间更均匀 |
💡 电梯算法类比: 电梯不会为了按了 15 楼的人而改变方向——它会按照当前方向一直走到尽头,再折返。
6.2 I/O 控制方式
① 程序查询方式(Programmed I/O)
原理: CPU 不断检查设备状态——“设备准备好了吗?”
CPU: 好了吗?→ 设备: 没好 → CPU: 好了吗?→ 设备: 没好 → ... → 设备: 好了!
- ❌ CPU 被占用,效率极低
类比: 你一直盯着电饭煲看饭熟了没有——没法做其他事。
② 中断控制方式(Interrupt-driven I/O)
原理: CPU 发起 I/O 操作后去做其他事,设备完成后发送中断信号通知 CPU。
CPU 发起 I/O → 继续做其他事 ─┐
│
设备完成 → 发送中断信号 → CPU 暂停当前工作
↓
CPU 处理中断 → 恢复之前的工作
- ✅ CPU 利用率大大提高
类比: 电饭煲做好饭后"叮"一声通知你,你可以利用等待时间做其他事。
中断处理流程:
- 设备发出中断信号
- CPU 完成当前指令
- 保存当前状态(程序计数器、寄存器等)
- 确定中断来源
- 执行中断处理程序
- 恢复状态,继续执行
中断向量表: 存储各种中断对应的处理程序入口地址
中断向量号 0 → 时钟中断
中断向量号 1 → 键盘中断
中断向量号 2 → 磁盘中断
中断向量号 3 → 软件中断
...
③ DMA 方式(Direct Memory Access)
原理: DMA 控制器直接在设备和内存之间传输数据,无需 CPU 参与数据搬运。
数据传输时:
CPU → 做其他事(计算)
DMA控制器 → 负责 I/O 数据传输
设备 ↔ DMA ↔ 内存
完成后 → DMA 发送中断通知 CPU
- ✅ 极大提高效率,解放 CPU
类比: 你(CPU)安排快递员(DMA)去搬东西,你继续做自己的事。
DMA 传输步骤:
- CPU 设置 DMA 寄存器(数据源地址、目标地址、字节数)
- CPU 通知 DMA 开始传输
- DMA 控制总线进行数据传输
- 传输完成后,DMA 发送中断通知 CPU
④ 通道控制方式
- 使用专门的 I/O 通道处理器 管理 I/O
- 通道有自己的指令,可以执行复杂的 I/O 程序
- CPU 只需发出一个 I/O 指令,其余由通道完成
是大型机(IBM 370)中使用的高级 I/O 方式。
6.3 中断机制
中断(Interrupt) — 设备通知 CPU 的一种机制。
中断类型:
| 中断类型 | 来源 | 例子 |
|---|---|---|
| 硬件中断 | 外部设备 | 键盘按下、磁盘完成 |
| 软件中断(陷阱) | 程序主动触发 | 系统调用请求 |
| 异常 | CPU 内部 | 除零错误、缺页 |
中断优先级:
- 多个中断可同时发生时,优先级高的先处理
- 高优先级中断可以打断低优先级中断的处理
典型中断优先级(从高到低):
- 机器故障中断(如电源故障)
- 时钟中断
- 磁盘中断
- 网络中断
- 键盘/鼠标中断
6.4 缓冲技术
缓冲区: 内存中用于临时存放 I/O 数据的区域。
为什么要缓冲?
- 协调 CPU 和 I/O 设备的速度差异
- 减少中断次数
- 解决数据粒度不匹配问题
缓冲方式:
- 单缓冲
- 双缓冲
- 循环缓冲
- 缓冲池
举例: 你打字很快,但打印机打印很慢。系统把要打印的内容存在缓冲区,一次性发给打印机。你继续打字,打印机慢慢打。
6.5 SPOOLing 技术
SPOOLing(Simultaneous Peripheral Operation On-Line) — 同时的外围设备联机操作。
通俗理解: 用磁盘模拟慢速设备,实现"虚拟设备"。
工作原理:
多个程序同时 "打印"
↓
输出到磁盘缓冲区(输入井/输出井)
↓
SPOOLing 守护进程依次发送到真实打印机
典型应用:打印机共享
- 多个程序可以同时"打印"(实际输出到磁盘)
- SPOOLing 系统依次把缓冲区的内容送到真实打印机
- 用户无需等待其他程序完成打印
6.6 I/O 软件层次结构
用户态
┌────────────────────┐
│ 用户 I/O 库函数 │ ← printf(), scanf(), read(), write()
├────────────────────┤
│ 用户进程 │
├────────────────────┤
核心态
├────────────────────┤
│ 设备无关的 I/O 软件 │ ← 缓冲、错误处理、分配
├────────────────────┤
│ 设备驱动程序 │ ← 与硬件相关的代码
├────────────────────┤
│ 中断处理程序 │ ← 处理设备中断
├────────────────────┤
│ 硬件 │ ← 实际设备
└────────────────────┘
6.7 设备驱动程序
- 每种设备都有对应的驱动程序
- 驱动程序是操作系统与硬件设备之间的"翻译官"
- 统一 I/O 接口,屏蔽设备差异
类比: 同样的 USB 接口,插入不同设备需要装不同驱动——就像插座标准化,但电器内部各不相同。
第 7 章 用户接口服务
7.1 用户接口的类型
操作系统提供两种用户接口:
① 命令行接口(CLI)→ 输入命令 → 如:ls, cd, mkdir
② 图形用户接口(GUI)→ 点击图标 → 如:Windows, macOS
7.2 系统调用
系统调用(System Call) — 程序请求操作系统服务的方式。
通俗理解: 应用程序不能直接操作硬件,必须通过"系统调用"请求操作系统帮忙。
就像你不能直接去厨房拿菜(直接访问硬件),而是通过服务员(系统调用)下单。
系统调用的分类
| 类别 | 系统调用 | 说明 |
|---|---|---|
| 进程控制 | fork(), exit(), wait(), exec() |
创建/终止/等待进程 |
| 文件操作 | open(), read(), write(), close() |
读写文件 |
| 设备管理 | ioctl() |
控制设备 |
| 信息维护 | getpid(), alarm(), sleep() |
获取/设置系统信息 |
| 通信 | pipe(), shmget(), socket() |
进程间通信 |
系统调用的执行过程
① 应用程序调用库函数 (如 printf())
↓
② 库函数准备参数
↓
③ 执行陷阱指令 (trap),从用户态切换到核心态
↓
④ 操作系统内核根据系统调用号查找 sysent[] 表
↓
⑤ 执行对应的内核服务函数
↓
⑥ 返回结果,从核心态切回用户态
系统调用表(sysent):
系统调用号 0 → nosys(无效调用)
系统调用号 1 → exit
系统调用号 2 → fork
系统调用号 3 → read
系统调用号 4 → write
系统调用号 5 → open
系统调用号 6 → close
系统调用的参数传递
- 通过寄存器传递(最快,但参数数量有限)
- 通过内存块传递(参数多时使用)
- 通过堆栈传递
7.3 Shell(命令行解释器)
Shell — 用户和操作系统之间的命令行接口。
常见 Shell 类型
| Shell 名称 | 特点 |
|---|---|
| sh(Bourne Shell) | UNIX 最早的 Shell |
| bash(Bourne Again Shell) | Linux 默认,功能强大 |
| csh(C Shell) | 类似于 C 语言语法 |
| ksh(Korn Shell) | 兼容 sh,功能更丰富 |
Shell 的功能
- 命令解释 — 解析用户输入的命令
- 命令执行 — 创建子进程执行命令
- I/O 重定向 —
>(输出重定向)、<(输入重定向) - 管道 —
|将一个命令的输出作为另一个命令的输入 - 环境管理 — 设置环境变量
- 编程 — 支持脚本编程
Shell 的工作流程
Shell 显示提示符 $ → 用户输入命令
↓
Shell 解析命令(分解为命令名 + 参数)
↓
Shell 创建子进程(fork)
↓
子进程执行命令(exec)
↓
Shell 等待子进程完成(wait)
↓
Shell 显示下一个提示符 $
这不是 Windows 命令提示符(cmd)吗?
原理一样,但语法不同。cmd 是 Windows 的命令解释器。
7.4 Shell 编程示例
简单脚本 ex1.sh:
#!/bin/bash
date # 显示日期
pwd # 显示当前目录
cd .. # 切换到上级目录
带逻辑的脚本 ex2.sh:
#!/bin/bash
# 如果没有参数,则列出当前目录
# 否则,列出每个子目录
if test $# = 0
then
ls .
else
for i
do
ls -l $i | grep '^d'
done
fi
7.5 图形用户界面(GUI)
GUI 的发展里程碑:
- 1984 年:Macintosh 首次普及 GUI
- 1990 年:Windows 3.0
- 1995 年:Windows 95(开始菜单)
- 现在:Windows 11、macOS、GNOME、KDE
X Window 系统
特点: 独特的客户端-服务器架构
- 应用程序(客户端)和显示(服务器)分离
- 可以在远程计算机上显示图形界面
- 网络透明性
X Window 架构:
┌───────────────┐ 网络 ┌───────────────┐
│ X Server │ ◄──────────► │ X Client │
│ (本机显示) │ │ (远程程序) │
└───────────────┘ └───────────────┘
GNOME 和 KDE
| 桌面环境 | 特点 | 底层库 |
|---|---|---|
| GNOME | 简洁易用,Red Hat 默认 | GTK+ |
| KDE | 功能丰富,可配置性强 | Qt |
7.6 API 与系统调用的关系
应用程序代码
↓ 调用
API(应用程序编程接口)
├── 如:C 标准库 `printf()`
├── 如:Win32 API `CreateWindow()`
└── 如:Java API `FileInputStream.read()`
↓ 内部调用
系统调用(操作系统内核服务)
API 是提供给程序员的函数接口,系统调用是 API 底层真正去请求操作系统的机制。
第 8 章 死锁
8.1 什么是死锁?
定义: 多个进程互相等待对方占有的资源,导致所有相关进程都无法继续执行的状态。
通俗理解: 两个人在独木桥上相遇,你等他让,他等你让——结果谁都走不了。
经典例子:
进程 A 拿着资源 1,请求资源 2
进程 B 拿着资源 2,请求资源 1
→ A 等 B,B 等 A → 陷入死锁!
8.2 死锁的四个必要条件
四个条件必须同时满足才会发生死锁! 破坏任意一个,死锁就不会发生。
| 条件 | 名称 | 通俗解释 |
|---|---|---|
| 1️⃣ | 互斥(Mutual Exclusion) | 一个资源一次只能被一个进程使用 |
| 2️⃣ | 占有并等待(Hold and Wait) | 进程占有一个资源,同时等待其他资源 |
| 3️⃣ | 不可剥夺(No Preemption) | 资源只能由进程主动释放,系统不能强行拿走 |
| 4️⃣ | 循环等待(Circular Wait) | 存在一个循环链,每个进程都在等链中下一个进程的资源 |
麻将类比: 四个人打麻将准备胡牌,每人各缺一张特定的牌。
- 互斥:每张牌在桌上只有一张
- 占有并等待:每人手上有牌,还想要别人手里的牌
- 不可剥夺:不能抢别人手上的牌
- 循环等待:A 要 B 的、B 要 C 的、C 要 D 的、D 要 A 的
→ 死局!
8.3 资源分配图
图形化分析死锁的工具:
| 图形元素 | 含义 |
|---|---|
| ○(圆圈) | 进程 |
| □(方块) | 资源(圆点表示资源实例数量) |
| ← (进程→资源) | 进程请求资源 |
| ← (资源→进程) | 资源已分配给进程 |
判断规则:
- 图中没有环 → 没有死锁 ✅
- 图中有环,且每个资源只有一个实例 → 必然死锁 ❌
- 图中有环,但资源有多个实例 → 可能死锁,需要进一步分析
8.4 处理死锁的四种策略
┌──────────────────────────────────┐
│ 死锁问题处理 │
├──────────────────────────────────┤
│ ① 死锁预防(严格预防,代价高) │
│ ② 死锁避免(银行家算法,较灵活) │
│ ③ 死锁检测与恢复(允许发生再处理) │
│ ④ 鸵鸟策略(忽略死锁) │
└──────────────────────────────────┘
① 死锁预防
破坏四个必要条件之一:
| 破坏条件 | 方法 | 代价 |
|---|---|---|
| 破坏互斥 | 用虚拟化技术(如打印机的 SPOOLing) | 对不可共享资源不适用 |
| 破坏占有并等待 | 一次性申请所有资源 | 资源利用率低 |
| 破坏不可剥夺 | 系统可以强行收回资源 | 实现复杂,可能丢失工作 |
| 破坏循环等待 | 资源编号,按顺序申请 | 编号困难,资源利用率低 |
② 死锁避免(银行家算法)
创始人: Dijkstra(1965 年)
核心思想: 像一个谨慎的银行家,放贷前判断:如果放贷会导致资金链断裂(死锁),就拒绝。
数据结构:
| 结构 | 含义 |
|---|---|
| Available[m] | 每种资源当前可用的数量 |
| Max[n][m] | 每个进程对每种资源的最大需求 |
| Allocation[n][m] | 每个进程已分配的资源数量 |
| Need[n][m] | 每个进程还需要的资源数量(Need = Max - Allocation) |
算法流程:
① 进程 Pi 请求资源 Request[i]
② 如果 Request[i] > Need[i] → 错误(超过声明需求)
③ 如果 Request[i] > Available → 暂时无法满足,等待
④ 系统"假装"分配资源:
Available = Available - Request[i]
Allocation[i] = Allocation[i] + Request[i]
Need[i] = Need[i] - Request[i]
⑤ 执行"安全性检查"(判断是否处于安全状态)
⑥ 安全 → 真正分配;不安全 → 回滚,让进程等待
安全性检查:
① 设置 Work = Available, Finish[1..n] = false
② 找一个 Finish[i] = false 且 Need[i] ≤ Work 的进程
③ 如果找到 → Work = Work + Allocation[i], Finish[i] = true, 回到 ②
④ 如果所有 Finish[i] = true → 系统处于安全状态 ✅
否则 → 不安全 ❌
安全状态: 存在一个进程执行序列,让所有进程都能完成。
不安全状态 ≠ 死锁,但不安全状态可能演变为死锁。
③ 死锁检测与恢复
允许死锁发生,但定期检测并恢复。
检测方法:
- 用资源分配图分析是否存在循环等待
- 定期运行检测算法
恢复方法:
- 终止进程:终止所有死锁进程,或逐个终止直到死锁解除
- 资源抢占:从部分进程收回资源给其他进程
- 选择"受害进程"(代价最小)
- 回滚到安全状态
④ 鸵鸟策略
“把头埋进沙子里,假装没看到问题。”
- 大多数个人电脑操作系统(Windows、Linux)采用此策略
- 死锁发生的概率远低于预防/避免的代价
8.5 经典同步问题
生产者-消费者问题
问题描述:
- 生产者不断产生数据放到缓冲区
- 消费者不断从缓冲区取出数据处理
- 缓冲区满了生产者要等,缓冲区空了消费者要等
用信号量解决:
semaphore mutex = 1; // 互斥访问缓冲区
semaphore empty = N; // 空位数量
semaphore full = 0; // 已填满的缓冲区数量
// 生产者
while(TRUE) {
produce_item();
P(empty); // 空位减一,如果没有空位则等待
P(mutex); // 进入临界区
put_item();
V(mutex); // 离开临界区
V(full); // 满位加一
}
// 消费者
while(TRUE) {
P(full); // 满位减一,如果没有则等待
P(mutex); // 进入临界区
get_item();
V(mutex); // 离开临界区
V(empty); // 空位加一
consume_item();
}
⚠️ 注意: PV 操作的顺序很重要!如果生产者先
P(mutex)再P(empty),当缓冲区满时,生产者会拿着互斥锁等待空位——消费者无法进入临界区消费 → 死锁!
第 9 章 嵌入式操作系统
9.1 什么是嵌入式系统
通俗理解: 专门用于特定设备的"小电脑"——不是通用计算机,而是某个设备内部的"大脑"。
无处不在的嵌入式系统:
| 领域 | 例子 |
|---|---|
| 消费电子 | 智能手机、智能手表、智能电视 |
| 汽车 | 发动机控制系统、ABS 刹车系统、车载娱乐系统 |
| 家用电器 | 洗衣机、微波炉、智能冰箱 |
| 医疗设备 | 心脏起搏器、CT 扫描仪 |
| 工业控制 | PLC、机器人控制器 |
| 网络设备 | 路由器、交换机、基站 |
| 军事/航空 | 导弹制导、飞行控制 |
9.2 嵌入式操作系统的特点
| 特点 | 说明 |
|---|---|
| 小型化 | 代码量小(几十KB到几MB),占用内存少 |
| 实时性 | 必须在规定的时限内响应外部事件 |
| 专用性 | 针对特定硬件和应用定制优化 |
| 可靠性 | 不能崩溃(特别是安全关键系统) |
| 低功耗 | 电池供电,功耗必须严格控制 |
| 成本敏感 | 硬件成本必须低 |
9.3 实时操作系统(RTOS)
实时系统分类:
| 类型 | 特点 | 错过截止时间的后果 | 例子 |
|---|---|---|---|
| 硬实时 | 严格,绝对不能超时 | 灾难性后果 | 安全气囊、飞行控制 |
| 软实时 | 偶尔超时可以接受 | 性能下降 | 视频播放、在线游戏 |
RTOS 的核心功能
| 功能 | 说明 |
|---|---|
| 任务管理 | 多任务调度,优先级管理 |
| 中断管理 | 快速响应外部中断 |
| 时钟管理 | 精确计时,定时器管理 |
| 内存管理 | 快速、可预测的内存分配(通常不用 MMU) |
| I/O 管理 | 管理各种传感器和外设 |
| 同步与通信 | 信号量、消息队列、邮箱等 |
优先级反转(Priority Inversion)
问题: 高优先级任务被低优先级任务阻塞,因为低优先级任务占用了高优先级需要的共享资源。
优先级高 ─── 任务H(等待资源R)
优先级中 ─── 任务M(执行,抢占低优先级)
优先级低 ─── 任务L(持有资源R)
时间线:
1. 任务L 获得资源R,开始执行
2. 任务H 被唤醒,需要资源R,但 L 还持有 R → H 阻塞
3. 任务M 被唤醒,抢占 L(L 还未释放 R)→ M 执行
4. 任务H 虽然优先级最高,却要等到 M 和 L 都完成 → **优先级反转!**
解决方案:
- 优先级继承:当低优先级任务持有高优先级需要的资源时,临时获得高优先级
- 优先级天花板:给资源设置最高优先级,占有资源的任务继承该优先级
嵌入式系统中的中断处理
嵌入式系统对中断的响应时间要求极高。RTOS 通常做到:
- 中断延迟:从硬件中断发生到第一条中断指令执行的延迟
- 典型 RTOS 中断延迟:微秒级别
9.4 常见的嵌入式操作系统
| 系统 | 特点 | 应用领域 |
|---|---|---|
| VxWorks | 商业 RTOS,高可靠性 | 航空航天、工业控制 |
| FreeRTOS | 开源,轻量级 | 物联网、MCU |
| uC/OS | 可裁剪,适合教育 | 学习、中小型系统 |
| RT-Thread | 国产,开源,功能丰富 | 物联网、智能设备 |
| 嵌入式 Linux | 功能强大,但不是硬实时 | 路由器、智能设备 |
| Android | 基于 Linux 的移动系统 | 手机、平板 |
| iOS | Apple 移动系统 | iPhone、iPad |
9.5 华为鸿蒙操作系统(Harmony OS)
- 2019 年发布
- 面向"全场景"的分布式操作系统
- 核心理念:“一次开发,多端部署”
- 特点:
- 分布式架构(跨设备协同)
- 确定性时延引擎(硬实时能力)
- 弹性部署(按需裁剪)
- 统一 OS,适配不同设备(手机、平板、车机、IoT)
9.6 嵌入式系统的开发方式
- 交叉编译:在 PC 上编译,在嵌入式设备上运行
- JTAG/SWD 调试:通过调试接口连接开发板
- 裸机开发:没有 OS,直接在硬件上运行
- RTOS 开发:使用实时多任务系统
第 10 章 分布式系统和云计算
10.1 分布式系统概述
定义: 多台独立的计算机通过网络连接,协同工作,对外表现为"一台强大"的计算机。
就像很多蚂蚁一起搬食物,每只蚂蚁分担一部分重量,外人看起来就是"食物在移动"。
分布式系统的特点
| 特点 | 说明 |
|---|---|
| 资源共享 | 多台计算机共享硬件、软件、数据 |
| 并行性 | 多个任务在不同计算机上同时执行 |
| 透明性 | 用户感觉不到是多台计算机在协作 |
| 可扩展性 | 可以轻松增加更多计算机以提升性能 |
| 容错性 | 部分机器故障不影响整体服务 |
| 异构性 | 不同硬件、操作系统可以协同工作 |
分布式系统的挑战
- 通信延迟 — 网络传输比内存访问慢得多
- 时钟同步 — 不同计算机时钟不一致
- 一致性维护 — 多台计算机数据保持一致很困难
- 安全性 — 数据在网络传输中可能被窃取或篡改
- 故障处理 — 部分节点故障时的处理
10.2 分布式系统的关键技术
10.2.1 通信
远程过程调用(RPC):
- 让程序像调用本地函数一样调用远程计算机的函数
- 序列化/反序列化参数
- 网络传输透明化
类比: 你打电话给朋友(远程调用),让他帮你查个资料(远程执行),他在那边查完告诉你结果(返回结果)。
10.2.2 时钟同步
问题: 每台计算机的时钟不同步。
Lamport 逻辑时钟(1978 年):
- 不是同步时间,而是为事件排序
- 每个事件分配一个"逻辑时间戳"
- 如果 A → B(A 在 B 之前发生),则
LC(A) < LC(B)
向量时钟:
- 解决 Lamport 时钟无法检测"并发事件"的缺陷
- 每个节点维护一个向量,记录每个节点的最新时间
10.2.3 互斥
分布式互斥的三种方式:
| 方法 | 原理 | 特点 |
|---|---|---|
| 中央协调者 | 一个节点做"裁判" | 简单,但单点故障 |
| 令牌环 | 令牌依次传递,有令牌才能进临界区 | 无饥饿,但通信量随节点数线性增长 |
| 分布式投票 | 需要多数节点同意 | 容错性好,但通信量大 |
10.2.4 一致性模型
| 模型 | 宽松程度 | 说明 |
|---|---|---|
| 严格一致性 | 最严格 | 任何写入立即可见 |
| 顺序一致性 | 严格 | 所有节点看到的操作顺序一致 |
| 最终一致性 | 宽松 | 只要不写入新值,最终所有副本一致 |
| 因果一致性 | 中等 | 有因果关系的操作按序可见 |
生活类比: 微博的点赞数——你可能看到 100 赞,我可能看到 102 赞,过一会儿都会更新到正确的数字,这就是"最终一致性"。
10.2.5 负载均衡
目标: 将工作负载均匀地分配到多台计算机上。
常见方法:
- 轮询(Round Robin) — 轮流分配请求
- 最少连接 — 分配给当前连接最少的服务器
- 哈希分配 — 基于请求的某些特征(如客户端 IP)分配
- 加权分配 — 性能好的服务器分更多请求
10.3 分布式操作系统 vs 网络操作系统
| 对比 | 网络操作系统 | 分布式操作系统 |
|---|---|---|
| 耦合度 | 松散 | 紧密 |
| 透明性 | 用户知道有不同计算机 | 用户感觉不到 |
| 资源管理 | 每台计算机自主管理 | 全局统一管理 |
| 例子 | Windows 网络、NFS | Amoeba、Plan 9 |
中间件(Middleware): 在分布式系统和应用程序之间提供标准接口的软件层,屏蔽底层异构性。
┌──────────────────────┐
│ 应用程序 │
├──────────────────────┤
│ 中间件(Middleware) │ ← 提供分布式服务抽象
├──────────────────────┤
│ 操作系统 │
├──────────────────────┤
│ 网络 │
└──────────────────────┘
10.4 多处理器系统
| 系统类型 | 架构 | 例子 |
|---|---|---|
| 多处理器系统 | 共享内存,多个 CPU | SMP(对称多处理) |
| 多计算机系统 | 不共享内存,消息传递 | 集群 |
| 网络系统 | 松散耦合,通过网络连接 | 局域网工作站 |
| 分布式系统 | 紧密/松散耦合,协同工作 | 云计算平台 |
10.5 云计算
通俗理解: 通过网络按需获取计算资源(服务器、存储、软件),就像用水用电一样方便。
生活类比:
- 过去:每家自己打井取水(自己买服务器建机房)
- 现在:用自来水公司(云服务商)的水,打开水龙头就有,按用量付费
云计算的三种服务模式
┌──────────────────────────────────┐
│ SaaS │
│ 软件即服务(Software as a Service)│
│ 直接用软件(如:Google Docs、企业微信)│
├──────────────────────────────────┤
│ PaaS │
│ 平台即服务(Platform as a Service) │
│ 在平台上开发部署(如:Google App Engine)│
├──────────────────────────────────┤
│ IaaS │
│ 基础设施即服务(Infrastructure...)│
│ 租用服务器/存储(如:AWS EC2) │
└──────────────────────────────────┘
通俗化解释:
| 服务模式 | 自己管的 | 云服务商管的 |
|---|---|---|
| IaaS | 操作系统、应用、数据 | 硬件、网络、虚拟机管理 |
| PaaS | 应用、数据 | 硬件、操作系统、运行时 |
| SaaS | 数据(部分) | 一切(硬件、平台、软件) |
云的核心特性
| 特性 | 说明 |
|---|---|
| 按需自助 | 需要就开,用完就关 |
| 广泛网络访问 | 有网就能用 |
| 资源池化 | 多用户共享物理资源(逻辑隔离) |
| 快速弹性 | 根据负载自动伸缩 |
| 可计量服务 | 用多少付多少 |
部署模型
| 部署方式 | 说明 |
|---|---|
| 公有云 | 第三方服务商提供,多租户 |
| 私有云 | 企业自建,仅供内部使用 |
| 混合云 | 公有云 + 私有云结合 |
| 社区云 | 多个组织共同使用 |
第 11 章 安全与保护机制
11.1 安全问题的来源
操作系统面临的安全威胁:
| 威胁类型 | 说明 | 例子 |
|---|---|---|
| 病毒 | 自我复制的恶意程序 | 蠕虫、文件感染病毒 |
| 木马 | 伪装成正常程序的恶意软件 | 伪装成游戏、破解工具 |
| 蠕虫 | 通过网络自我传播 | Stuxnet 震网病毒 |
| 间谍软件 | 窃取用户信息 | 键盘记录器 |
| 后门 | 绕过正常认证的隐蔽入口 | 系统后门 |
| 拒绝服务(DDoS) | 让系统无法正常服务 | 大量请求淹没服务器 |
| 社会工程学 | 欺骗用户泄露信息 | 钓鱼邮件 |
11.2 安全目标
CIA 三要素:
┌─────────────────┐
│ 机密性(C) │ ← 信息只能被授权者访问
├─────────────────┤
│ 完整性(I) │ ← 信息不被非法篡改
├─────────────────┤
│ 可用性(A) │ ← 系统能正常提供服务
└─────────────────┘
其他重要目标:
- 认证(Authentication) — 验证用户身份真伪
- 授权(Authorization) — 确定用户能做什么
- 审计(Audit) — 记录操作日志,事后追责
- 不可否认性(Non-repudiation) — 用户不能否认自己的操作
11.3 威胁与攻击
| 攻击类型 | 机理 | 防范 |
|---|---|---|
| 缓冲区溢出 | 输入数据超过了缓冲区的边界 | 边界检查、ASLR |
| SQL 注入 | 在输入中嵌入 SQL 代码 | 参数化查询 |
| 跨站脚本(XSS) | 在网页中注入恶意脚本 | 输入验证、转义 |
| 中间人攻击 | 拦截通信双方的数据 | 加密传输(HTTPS) |
| 权限提升 | 从普通用户获取管理员权限 | 最小特权原则 |
11.4 访问控制
11.4.1 最小特权原则
Principle of Least Privilege
每个用户/程序只拥有完成其任务所需的最小权限。
举例:
- 前台只需要"查看订单"权限,不需要"删除订单"权限
- 普通用户不需要系统管理权限
11.4.2 访问控制矩阵
文件A 文件B 文件C 打印机
用户1 读 读/写 - 使用
用户2 读/写 - 读 -
用户3 - 读 写/执行 使用
实现方式:
| 方式 | 方向 | 存储方式 | 优点 | 缺点 |
|---|---|---|---|---|
| ACL(访问控制列表) | 面向文件 | 每个文件记录访问者列表 | 容易查看文件权限 | 删除用户麻烦 |
| 能力列表 | 面向用户 | 每个用户记录可访问的资源 | 容易查看用户权限 | 撤销权限麻烦 |
11.4.3 UNIX 权限控制
UNIX 中每个文件有三组权限:
rwx r-x r--
─┼─ ─┼─ ─┼─
│ │ └── 其他人权限(other)
│ └──────── 同组权限(group)
└────────────── 所有者权限(owner)
权限位含义:
- r(4)= 读
- w(2)= 写
- x(1)= 执行
例子: rwxr-xr--
- 所有者:读+写+执行
- 同组用户:读+执行
- 其他用户:只读
11.4.4 访问控制列表(ACL)
ACL(Access Control List) — 为每个文件列出哪些用户可以访问以及权限。
文件 F 的 ACL:
┌──────────┬───────┐
│ 用户 Alice │ read │
│ 用户 Bob │ write │
│ 组 staff │ read │
│ 其他人 │ none │
└──────────┴───────┘
11.4.5 能力列表(Capability List)
与 ACL 相反: 不是"文件→谁可以访问",而是"用户→可以访问什么"。
就像你的钥匙扣上有不同的钥匙(能力),每把钥匙可以开特定的门。有了钥匙就能开门,没钥匙就不能。
11.5 可信系统
TCB(Trusted Computing Base,可信计算基) — 系统安全的基础组件集合。
TCB 包含:
- 硬件(CPU、内存管理单元)
- 操作系统内核的安全部分
- 安全相关的系统调用
- 认证模块
11.6 安全评估标准
TCSEC(美国国防部可信计算机系统评估标准,“橙皮书”)
| 级别 | 名称 | 描述 |
|---|---|---|
| D | 最低保护 | 无安全措施 |
| C1 | 自主安全保护 | 基本的用户认证、文件权限 |
| C2 | 受控访问保护 | 更细粒度访问控制、审计日志 |
| B1 | 标签安全保护 | 给数据和用户加安全标签 |
| B2 | 结构化保护 | 形式化安全模型 |
| B3 | 安全域 | 高可靠性、最小权限 |
| A1 | 验证设计 | 形式化验证安全 |
UNIX 系统通常达到 C2 级别。
11.7 加密与认证
加密(Encryption): 将数据转换成只有授权方才能理解的形式。
对称加密:
- 加密和解密用同一个密钥
- 算法:DES、AES
- 优点:速度快
- 缺点:密钥分发困难
非对称加密:
- 使用公钥和私钥
- 算法:RSA、ECC
- 优点:密钥分发方便
- 缺点:速度慢
数字签名: 用私钥签名,用公钥验证——确保信息完整性和来源真实性。
认证方式
| 方式 | 安全级别 | 例子 |
|---|---|---|
| 密码认证 | 低 | 用户名+密码 |
| 双因素认证 | 中 | 密码+手机验证码 |
| 生物特征 | 高 | 指纹、人脸、虹膜 |
11.8 保护机制
用户态与核心态:
- 用户态 — 受限运行。应用程序运行在用户态
- 核心态 — 可执行特权指令。操作系统内核运行在核心态
CPU 的保护环(Ring 0 ~ Ring 3):
Ring 0 ── 操作系统内核(最可信) ← 所有权限
Ring 1 ── 设备驱动程序
Ring 2 ── 系统服务
Ring 3 ── 应用程序(最不可信) ← 受限权限
🧠 学习路线建议(小白友好版)
第1章:操作系统引论
└── 建立整体概念
第2章:进程和线程
└── 核心概念:程序怎么运行
第8章:死锁
└── 理解资源竞争问题
第4章:存储管理
└── 核心概念:内存怎么管理
第5章:文件系统
└── 核心概念:文件怎么存储
第6章:输入输出管理
└── 核心概念:设备怎么控制
第3章:调度
└── 深入:CPU 怎么分配
第7章:用户接口服务
└── 实操:系统调用、Shell
第11章:安全与保护
└── 扩展:怎么保证安全
第9章:嵌入式系统
└── 扩展:小设备上的 OS
第10章:分布式与云计算
└── 扩展:多台计算机协同
🔑 核心概念速查表
| 概念 | 一句话概括 |
|---|---|
| 操作系统 | 管理硬件和软件资源的"大管家" |
| 进程 | 正在执行的程序(有独立内存空间) |
| 线程 | 进程内的"子任务"(共享内存空间) |
| PCB | 进程的"身份证" |
| 调度 | 决定谁用 CPU、用多久 |
| 虚拟内存 | 让程序以为有超大内存(实际部分在硬盘) |
| 分页 | 把内存分成 4KB 小格子管理 |
| 缺页中断 | 要访问的页不在内存中 |
| 文件系统 | 硬盘上文件的组织管理方式 |
| i-node | 文件的"ID 卡"(UNIX) |
| 中断 | 设备通知 CPU 的方式 |
| DMA | 设备直接和内存交换数据,不经过 CPU |
| 系统调用 | 程序请求操作系统服务 |
| Shell | 命令行解释器(人机交互) |
| 死锁 | 进程互相等待,谁都动不了 |
| 银行家算法 | 避免死锁的"放贷"判断方法 |
| 嵌入式系统 | 专用设备中的"小系统" |
| 分布式系统 | 多台计算机协同工作 |
| 云计算 | 按需租用计算资源 |
| ACL | 文件的"门禁名单"(谁可以访问) |
| 最小特权 | 只给完成任务所需的最小权限 |
📝 本笔记基于操作系统教材 11 章内容整理,补充了实际案例和通俗解释。
欢迎在学习过程中随时补充笔记、画思维导图,把知识真正内化!
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)