操作系统是所有基础设施坐落的地板:进程怎么调度、内存怎么映射、I/O 怎么多路复用,直接决定了你写的服务的上限。这个模块的目标不是背概念,而是通过 xv6 这种能编译跑起来的教学内核把抽象拆开看一遍,之后再看 Linux 的行为就有参照物。
学完后你应该能回答
进程 / 虚拟内存 / fork
- 进程和线程共享什么、不共享什么?fork 之后的写时复制是怎么实现的?
- 页表多级结构解决了什么问题?一次 TLB miss 的代价大概多大,TLB shootdown 是怎么回事?
- 缺页中断(page fault)的处理流程是什么?major fault 和 minor fault 的区别?
- 从用户态系统调用到内核态执行,中间走过哪些步骤(陷入、上下文切换、返回)?
- Copy-on-write 在 fork 之后的具体时机是什么?一个大内存进程 fork + exec 的代价为什么还相对小?
- huge page / transparent huge page 解决的是什么问题?数据库为什么常常建议关 THP?
- 进程状态 R / S / D / Z 各意味着什么?D 状态为什么连 SIGKILL 都杀不掉?
- ASLR / NX / KASLR 分别在哪一层工作?它们各防哪类攻击?
文件系统 / I/O / 多路复用
- mmap 和 read/write 在性能上的区别是什么?什么场景下应该用 mmap,什么场景下反而更慢?
- epoll 相比 select/poll 的优势在哪?边缘触发(ET)和水平触发(LT)怎么选?
- io_uring 和 epoll 的核心区别是什么?它解决了哪些 epoll 解决不了的问题?
- 零拷贝系统调用(sendfile、splice、tee、MSG_ZEROCOPY)各自适合什么场景?
- 写入磁盘链路 write → page cache → writeback → device queue,fsync / fdatasync 分别等到哪一步?
- ext4、XFS、Btrfs 在日志方式、元数据并发、snapshot 上的主要差异?数据库选型时怎么考虑?
- direct I/O(O_DIRECT)绕开 page cache 的代价和收益?为什么 PostgreSQL 不用它而 MySQL/InnoDB 用?
调度 / cgroup / 容器
- Linux 的 CFS 和 EEVDF 调度器是怎么分配 CPU 时间的?nice 值和 cgroup cpu.weight 的关系是什么?
- cgroup v1 和 v2 的核心差异?容器里的 CPU / 内存限制底层走的是哪些 controller?
- OOM killer 怎么打分(oom_score / oom_score_adj)?为什么内存最多的进程不一定先被杀?
- futex 和用户态 mutex 的关系?无竞争时为什么几乎不走系统调用?
- 容器隔离涉及哪些 namespace(pid / net / mnt / uts / ipc / user)?user namespace 为什么是安全的关键?
- seccomp / capabilities / AppArmor / SELinux 分别在哪一层限制进程?runc 默认拒绝哪些 syscall?
- CFS 的 cpu.cfs_period_us / cpu.cfs_quota_us 组合会产生什么 throttle 现象?在线上延迟敏感服务上为什么常常要关 CPU limit?
性能 & 观测
- 如何用 strace 定位一个卡住的进程?perf 采样和 bpftrace 追踪各适合什么问题?
- USE 方法(Utilization / Saturation / Errors)在排查机器卡顿时具体怎么逐项看?
- perf record 采样栈为什么需要 frame pointer / libunwind / DWARF 三选一?它们各自的 overhead 和准确度差在哪?
- eBPF 为什么被称为”内核里安全跑程序”?verifier 拦住了哪些类型的坑?
- Top-down 方法学四象限(Frontend / Bad Speculation / Backend / Retiring)怎么判断一个热点循环到底卡在哪?
核心概念
-
内核调度的两类基本单位,分别承担隔离和共享的角色。搞清楚它们的地址空间、文件描述符、信号是怎么分的。
-
每个进程看到自己独占的连续地址空间,靠页表和 MMU 映射到物理内存。是理解 fork、mmap、OOM 的前置。
-
inode、目录、日志、页缓存这一套。看懂后你能解释为什么 fsync 贵、为什么小文件多会慢。
-
锁、条件变量、信号量、无锁数据结构。写多线程代码绕不过去,也是 xv6 lock lab 的直接目标。
-
Linux 的高效 I/O 多路复用机制,Nginx / Redis 的事件循环底座。理解 LT / ET 模式是基本要求。
-
Linux 新一代异步 I/O 接口,用共享环形队列把系统调用批处理化。高吞吐存储 / 网络栈正在往这里迁。
-
把文件或匿名内存映射进进程地址空间,共享内存和大文件随机访问的常用手段。用错会带来 SIGBUS 和诡异的页回写。
-
内核把运行时状态暴露成虚拟文件系统。线上排查时 /proc/
/maps、status、stack 是你最常打开的文件。 -
Brendan Gregg 的系统性排查框架:对每个资源看 Utilization / Saturation / Errors。机器卡住时按这三维扫一遍。
-
Intel 的 Frontend / Bad Speculation / Backend / Retiring 四象限分析法。用来判断热点循环到底卡在 CPU 的哪一环。
Lab
-
教学级 Unix-like 内核的实验套件。一套做下来,syscall、页表、锁、文件系统从概念变成你自己改过的代码。
-
用 xv6 的系统调用写小工具(xargs、find 等)。入门热身,熟悉 xv6 工作流。
-
往内核里加一个新系统调用。走完 trap 表、参数传递、返回值的全流程。
-
亲手动 RISC-V 的三级页表。做完你对虚拟地址翻译的理解会从 PPT 级别变成能画寄存器的级别。
-
重构内核里粗粒度锁,优化并发性能。直面锁争用和锁拆分的取舍。
-
在 xv6 里实现 mmap / munmap。懂了之后你再看 Linux mmap 的行为会觉得自然。
资料
-
三段式(虚拟化、并发、持久化)讲 OS,免费在线,语言直白。最适合当主线教材。
-
MIT 操作系统课主页,讲义 / 视频 / lab 全开放。和 OSTEP 搭配食用效果最佳。
-
逐行讲 xv6 源码的配套小册子。做 lab 时的最高频参考。
-
Linux 内核社区的权威新闻站。想追踪调度器、内存、io_uring 等主线演进,这里是唯一选择。
-
The Linux Programming Interface
Michael Kerrisk 的 Linux 系统编程百科全书。Linux 系统调用行为有疑问时翻它一般都有答案。
-
Systems Performance(Brendan Gregg)
Linux 系统性能的大百科。CPU / memory / disk / network 四大块按 USE 方法展开。
工具
-
追踪进程发出的系统调用和信号。卡住的进程、文件没打开、网络连不上,先 strace 一把基本不亏。
-
strace 的库调用版,看 libc / 动态库函数调用。排查 glibc 层面的奇怪行为有用。
-
Linux 原生的性能分析工具,采样 CPU、硬件事件、调度延迟。做 profile 的主力。
-
基于 eBPF 的高级追踪语言,一行脚本就能观测内核事件。比 strace 轻,比 perf 灵活。
-
在内核里安全跑沙盒程序的基础设施,bcc 是它的 Python 工具集。现代 Linux 可观测性的事实标准。
-
开源机器模拟器,xv6 就跑在它上面。想 debug 内核或玩其他架构(RISC-V、ARM)都离不开它。
-
内核函数追踪框架。排查系统调用、调度、IO 栈问题的主力,bpftrace 之外的经典路线。
-
把采样栈折叠成可视化图。perf record 之后第一件事就是 flame graph。