☰ 第 03 章 · 操作系统:理解内核行为
COURSE SOURCES

参考来源与版权说明

仅作来源说明 · 不提供原始资料下载
查看全部来源说明
01
START HERE

这章解决什么问题

应用发出一次读请求后,为什么有时消耗用户态 CPU,有时进入内核,有时睡眠,有时又在运行队列等待?本章提供解释这些现象的操作系统模型。内核负责调度、虚拟内存、文件系统、网络协议和设备驱动;应用通过库与系统调用请求特权服务。只有理解这条路径,才能把“进程没在跑”进一步解释成等待 CPU、I/O、锁、缺页或工作到来。

本章不要求记住所有内核实现,而是建立稳定概念,并提醒你:相同工具名在不同内核版本、配置、容器和虚拟机中可能看到不同范围的数据。

02
SECTION 02

五条核心结论

  1. 模式转换不等于上下文切换。 系统调用会从用户态进入内核态;只有线程阻塞、被抢占或调度给别的任务时,才发生任务上下文切换。
  2. 线程状态是性能导航图。 on-CPU、可运行等待、不可中断 I/O 等待和可中断睡眠,会把调查引向完全不同的资源。
  3. 内核通过抽象隐藏复杂性。 虚拟内存、VFS、套接字和设备驱动提供统一接口,也让一次请求跨越多层缓存和队列。
  4. 局部性影响调度质量。 CPU 亲和性、热缓存和 NUMA 内存位置会改变同一代码的执行成本。
  5. 版本与配置属于证据。 调度器、cgroup、PSI、eBPF、io_uring 等能力随内核演进;不能把另一台机器的行为直接套用。
03
SECTION 03

核心模型与关键指标

应用线程(用户态)
  ├─ 计算 ───────────────→ on-CPU 用户时间
  └─ 系统调用 → 内核态 ──→ 内核时间 / 文件系统 / 网络 / 驱动
                      ├─ 立即返回
                      └─ 阻塞 → 睡眠 → 中断/事件唤醒 → 可运行队列 → on-CPU
  • 用户时间与内核时间:分别表示执行应用代码和内核代码的 CPU 时间。高内核时间可由系统调用、中断或内核线程产生。
  • 运行队列与调度延时:线程已具备运行条件,却在等 CPU;这是 CPU 饱和度的直接方向。
  • 上下文切换:调度器保存一个任务并恢复另一个任务的执行上下文;频率高不自动等于有问题,要结合每次工作量与延时。
  • 缺页故障:虚拟地址尚未具备所需映射。轻微缺页不访问磁盘,主要缺页可能等待存储,两者代价不同。
  • 中断:设备完成 I/O 等异步事件可触发硬中断;软中断承担延后处理。中断工作消耗 CPU,却不一定记在目标进程名下。
  • 缓存:从应用缓存、数据库缓存、页缓存到设备缓存,命中可避开慢层;缓存竞争也会把问题跨组件传播。
04
SECTION 04

诊断步骤

  1. 记录内核、发行版、架构、CPU 拓扑、容器/虚拟化边界与资源限制。
  2. 画出目标请求从应用函数到系统调用、VFS/网络栈和设备的路径,标明可能缓存与队列。
  3. 先按线程区分:正在用户态或内核态执行、可运行等待、D 状态等待、S 状态睡眠,避免把所有 off-CPU 都叫作 I/O。
  4. 若用户时间高,剖析用户代码;若内核时间高,检查系统调用、中断和内核路径;若可运行等待高,检查 CPU 与配额。
  5. D 状态或主要缺页增加,沿文件系统、块 I/O 和内存压力继续;若大量 S 状态,区分等待工作、计时睡眠与锁等待。
  6. 检查是否只有单个 CPU、NUMA 节点或设备队列繁忙;整体均值可能掩盖局部热点。
  7. 用版本文档核实指标来源和功能开关,再选择更深的 tracepoint、kprobe 或 BPF 工具。
05
SECTION 05

常用工具与命令

uname -a
cat /proc/version
lscpu
cat /proc/loadavg
ps -eLo pid,tid,psr,stat,pcpu,comm
cat /proc/interrupts
cat /proc/softirqs
cat /proc/self/status
systemd-analyze
systemd-analyze critical-chain

这些命令只读取状态。ps 的字段和格式在不同实现中可能略有差异;systemd-analyze 仅适用于使用 systemd 的系统。/proc/interrupts 在容器内可能不可见或只反映命名空间允许的范围。若要用 strace、调试器或逐事件跟踪附加生产进程,应先在测试环境评估开销,因为它们可能改变目标时序。

06
SECTION 06

如何解读结果

  • STAT=R 表示正在运行或可运行,不代表此刻一定占有 CPU;D 通常表示不可中断睡眠,常见于 I/O,但还需栈或事件证据;S 可能只是正常等待工作。
  • 一个系统调用若立即完成,可能只有用户态/内核态模式转换;阻塞调用才可能让调度器切换到其他线程。
  • psr 显示线程最近所在 CPU。大量工作集中在一个逻辑 CPU,可能是单线程、亲和性、锁或中断映射问题。
  • /proc/interrupts/proc/softirqs 是累计计数;应按时间取差值,并查看是否集中在特定 CPU,不能直接比较不同运行时长的主机。
  • 启动慢时,systemd-analyze critical-chain 显示关键依赖路径;blame 的单项耗时不一定处于真正阻塞启动完成的路径上。
  • 虚拟机或容器内看到的是被虚拟化和限制后的系统。主机空闲不代表租户未被 CPU 配额、内存上限或 I/O 控制节流。
07
SECTION 07

常见误判

  1. 把每次系统调用都叫上下文切换。 两者开销、原因和优化方向不同。
  2. 把 Linux 平均负载等同 CPU 队列。 它还可包含不可中断睡眠任务。
  3. 看到 `D` 就断言磁盘坏。 文件系统、网络文件系统、设备驱动或其他内核等待都可能出现类似状态。
  4. 只看进程不看线程。 单个热点线程会被进程平均值掩盖,多线程也可能受同一把锁限制。
  5. 把空闲内存少当作内存泄漏。 内核会利用内存做缓存,应结合可用内存、回收、换页与压力判断。
  6. 照搬旧内核经验。 cgroup 版本、I/O 调度器、PSI 和跟踪接口的可用性会改变指标含义与工具行为。
08
SECTION 08

五分钟自测

  1. 用一句话区分模式转换和上下文切换。
  2. 一个线程的 STATRDS 时,各自下一步最值得查什么?
  3. 为什么进程用户时间低,系统仍可能有很高的 CPU 消耗?
  4. 写出一次缓存未命中的文件读取可能经过的三层内核路径。
  5. 在容器内看到 CPU 空闲时,为什么仍要检查 cgroup 限制?
09
SECTION 09

本章小结

操作系统把应用与硬件连接起来:系统调用进入内核,调度器决定线程何时在哪颗 CPU 运行,虚拟内存和文件系统管理地址与数据,驱动及中断连接设备。诊断时先认清线程状态和执行模式,再沿实际数据路径深入;同时把内核版本、配置与资源边界纳入证据,避免把抽象接口误当成完整真相。

10
SECTION 10

来源定位

主题PDF 页码
操作系统术语与内核模型142-146
用户态/内核态、系统调用与中断146-151
时钟、进程生命周期与栈152-157
虚拟内存、调度器与文件系统157-161
缓存、网络、驱动、多处理器和资源管理161-164
UNIX、BSD、Solaris 与 Linux 背景165-168
Linux 性能能力、systemd 与 eBPF168-175
其他内核主题、比较与参考资料175-181
📝
QUICK CHECK

章节测验

5 道单选题。答错有解析,答对看来源页码。

单选题 · 第 1/5
已答 0/5

关于系统调用,哪项表述正确?

⚡ 用本章题目开始计时冲刺