第12讲 · 构建应用生态(Hacking Day)

2026 南京大学《操作系统原理》第十二讲 · 课堂实录重构

主讲 蒋炎岩(Yanyan Jiang)
视频 https://www.bilibili.com/video/BV17JDWBsEMi/
课程主页 https://jyywiki.cn/OS/2026/
本讲讲义 https://jyywiki.cn/OS/2026/lect12.md
讲义 / 幻灯片作者 蒋炎岩,https://jyywiki.cn/
讲义 / 幻灯片许可 CC BY-NC 4.0
图片来源 书中插图为课堂演示与讲义渲染图;演示类截图为视频画面

对应讲次:第12讲(南京大学 操作系统原理)

制作模型:deepseek-flash(coding-agent / pi;据 ~/.pi/agent/settings.json)

编者说明:本书由课堂录像的语音字幕重构而成,术语、章节骨架与参考链接已按课程官方讲义(lect12.md)校准。讲师的口语风格、类比与案例被尽量保留;编辑性的补充一律以「编者说明」或「编者拓展」标出。


引子:虚拟化的最后一课

(参考时间: 00:00)

不知不觉讲到 Virtualization 部分的最后一节课了。今天的 Hacking Day 算是一个回顾:操作系统上的应用生态是怎么构建起来的。「今天大部分内容考试不会出现,但可能对大家比较有用。」

回顾虚拟化讲过什么:从程序和进程 → 进程的地址空间 → 文件描述符(访问操作系统对象)→ C 标准库的实现 → 上节课的链接和加载。

「其实整个学期到现在,我一直在讲系统调用」——上节课讲的链接和加载,本质就是 execve 系统调用的行为:把 ELF 文件的 PT_LOAD 段搬到进程地址空间、设置栈上的 argc/argv/envp/auxv、让 PC 指向 interp 的入口……「我提到的一切,你在 strace 里都能看到。」

课程目标:通过阅读手册、指导 AI 写代码,理解任何系统调用,并且弄清楚为什么要这样设计。「这么复杂的东西,其实概念上也没什么困难——你建立正确的概念,就能知道里面每一个字节是怎么来的。」

今天讲三件事:① 这些系统调用是怎么来的;② 系统调用来了以后怎么把应用生态「长」起来;③ 应用生态本身。


一、见证历史

1.1 Unix 的演化

(参考时间: 00:05)

Dennis M. Ritchie:Evolution of the UNIX Time Sharing System——强烈推荐每个人都读一读。它讲 UNIX 怎么从零一点点实现成今天这样:

编者拓展|「从零开始」的启示:讲师说,所有复杂的东西在刚开始时都很简单。今天的大模型很可怕,但往前溯源,它们的雏形都很简单(就像并发课上那个能推理 GPT-2 的 gpt.c)。「Takeaway:不要害怕『不好』,大胆去做,并且持续改进。」

1.2 Minix:我「梦开始的地方」

(参考时间: 00:08)

Andrew S. Tanenbaum 写了 Minix:

Minix 1.7.5 在 QEMU 上启动:16-bit protected mode,如假包换的 UNIX v7 体验

📷 Minix 1.7.5 在 QEMU 上启动:16-bit protected mode,如假包换的 UNIX v7 体验
回到原视频 (00:13:00)

编者拓展|Minix 3 是「应用最广的操作系统」:讲师讲了个响亮的故事——Intel ME(管理引擎) 里那个独立的芯片 CPU 上跑的操作系统就是 Minix 3(因为它的许可证很宽松)。所以「每一台英特尔芯片组电脑里都有一个 Minix 3」,不管你实际用的是 Windows、Linux 还是别的系统。「Minix 3 一度是世界上应用最广的操作系统。」

Minix 体验有多完整?有 vi 编辑器、cc 编译器、man 手册(man 1 用户命令、man 2 系统调用、man 3 库函数)、cat | wc 管道、/usr/src 里全套内核与工具源代码——「你可以在 Minix 里改 Minix 的内核,然后自己编译、烧录、启动。」

Minix 里连 `man` 手册都有——和今天的 Linux 手册一模一样

📷 Minix 里连 `man` 手册都有——和今天的 Linux 手册一模一样
回到原视频 (00:16:00)

编者拓展|微内核(microkernel):Tanenbaum 在 1987 年就想做一个只有一个系统调用的操作系统——send/receive。文件系统、CPU 管理、内存管理都变成运行在用户态的服务进程(「A 同学负责文件系统、B 同学管 CPU、C 同学管内存」),进程之间发消息。这在当时非常超前、也不被看好(性能太差)。Andy 一直说:「我做 Minix 是为了上课,性能不是我要管的。」——「但我觉得很快微内核可能就要复活了(比如鸿蒙)。」

1.3 Linux 的诞生(1991 年 8 月 25 日)

(参考时间: 00:20)

Hello, everybody out there using minix – I'm doing a (free) operating system (just a hobby, won't be big and professional like gnu) for 386(486) AT clones. This has been brewing since April, and is starting to get ready. —— Linus Torvalds(时年 21 岁)

发布在 comp.os.minix(「相当于百度贴吧」)。早期的 Linux 还依赖 Minix 的工具链(磁盘要格式化成 Minix 文件系统),上面跑着 GNU gcc、bash……

comp.os.minix 上那条帖子:「just a hobby, won't be big and professional like gnu」

📷 comp.os.minix 上那条帖子:「just a hobby, won't be big and professional like gnu」
回到原视频 (00:23:00)

编者拓展|「合适的人 × 合适的时间」:讲师说,合适的人在合适的时间做成了事;但更有意思的是,更多「合适的人在不合适的时间做了合适的事」——比如 Frank Rosenblatt 的 Perceptron 论文(1958),受人类神经元启发、权重学出来,「这不就是今天的深度神经网络吗?」——但直到 2012 年才有 AlexNet。因为当时没有算力、也没有氛围,中间还经历了人工智能寒冬。「我们需要正确的时间、正确的地点、合适的人。」

1.4 名场面:质疑、回应与时代的车轮

(参考时间: 00:25)

「The single worst company we've ever dealt with…」(2012):那年 Alex Krizhevsky、Ilya Sutskever、Geoffrey Hinton 还在搞 AlexNet,NVIDIA 在 2006 年推出了那些年「反人类」的 CUDA 编程模型,Linus 在邮件列表里对 NVIDIA 竖了中指——天道好轮回:「能想象 NVDA 是现在市值最高的公司?」

Linus 与 NVIDIA 的名场面:当年「最烂的公司」,今天市值第一

📷 Linus 与 NVIDIA 的名场面:当年「最烂的公司」,今天市值第一
回到原视频 (00:27:00)

在 comp.os.minix 上,关于 Linux 的讨论越来越多,Tanenbaum 做了「官方回应」(「To me, writing a monolithic system is a truly poor idea」),Linus 完全不服气(全文);已经得了图灵奖的 Ken Thompson 也来回帖:

Generally agree that microkernels are probably the wave of the future. However, in my opinion it is easier to implement a monolithic kernel… easier for it to turn into a mess in a hurry as it is modified. —— Ken Thompson

时代成就的英雄:Linux 0.3.0 引入多处理器(一开始是 Big Kernel Lock,内核不能并行),2.4 内核才真正并行,2002 年才引入 RCU(Read-Copy-Update)无锁同步,2003 年 Linux 2.6 发布后随云计算开始起飞。

Linux 内核代码行数的增长:从 Hobby Project 到「泥潭」再到现代系统

📷 Linux 内核代码行数的增长:从 Hobby Project 到「泥潭」再到现代系统
回到原视频 (00:33:00)

编者拓展|「院士竟然可以下场来贴吧回帖」:讲师感慨,Ken Thompson(图灵奖得主,相当于「比中科院院士还高一级」)实名在论坛里回一个年轻人的帖子——「在我们这儿是一件政治不太正确的事……但如果有一天真的可以变成这样,我就去贴吧跟你们论战:你们写了个 CrazyOS,我就去跟你们互喷,喷完之后这个系统越变越好,那我觉得这绝对是值得的。」

1.5 同样的故事还在反复发生

(参考时间: 00:38)

编者拓展|caveman 的「精妙之处」:它用极致的 prompt 压缩输出,利用了 agent 的容错性——话少了会偶尔做错,但 agent 有自主性,发现做错就再试一次。只要准确率下降不太多,总体就能省下大量 token。「这是从 0 到 0.1 前所未有地容易的一个侧影。」

在 AI 帮助下读完一篇论文:讲师现场演示自己的流程——把 PDF 丢进共享文件夹,后台自动 OCR,产出一句话摘要 / 一段摘要 / 一页纸三个级别。「我可以在几分钟内看完一篇一百多页的博士论文。」这在以前无论如何做不到。


二、创造世界:从 initramfs 点亮 Linux

2.1 关于「初始状态」

(参考时间: 00:46)

「你只要能够问出这个问题:我们能不能控制 Linux 加载的第一个进程?—— 合理的事情就一定能做到。」

2.2 initramfs:最小的 Linux

(参考时间: 00:49)

我们写过最小的 x86-64 静态二进制——用系统调用打印一行、然后 exit:

; This is a Minimal Binary —— 不依赖任何库函数,直接做 write + exit 系统调用
最小 x86-64 二进制:「This is a Minimal Binary」

📷 最小 x86-64 二进制:「This is a Minimal Binary」
回到原视频 (00:50:00)

编者说明:讲师指出,这样的二进制在 ARM 树莓派上也能运行——因为加载器知道系统里有 QEMU,遇到别的体系结构的二进制文件会进入用户态模拟:所有用户态指令(move、计算、内存)被模拟执行,而系统调用直接转发给宿主操作系统。

要控制第一个进程,就需要一个 initramfs(initial RAM filesystem):execve 的第一个参数是 pathname,指向系统里的一个文件——但内核刚起来时还不知道你的文件系统在哪,所以最早的「文件」必须放在一个你能控制的内存文件系统里。

「如果你用 apt update 更新软件包,会看到一个耗时特别长的操作叫 update-initramfs——就是因为有些软件更新后要被重新打回这个最初始的文件系统。」

Linux 内核硬编码了一系列路径,会逐个尝试 execve:

graph LR
    K["Linux 内核完成最小初始化"] --> T{"依次尝试 execve"}
    T -->|"/sbin/init 不存在"| T2["/etc/init"]
    T2 -->|"不存在"| T3["/bin/init"]
    T3 -->|"…"| T4["直到成功"]
    T4 --> P["第一个进程诞生"]
    P --> S["操作系统变成『系统调用提供者』"]

打包过程:把目录树用 CPIO 归档 + gzip 压缩成 initramfs.cpio.gz,QEMU 启动时用 -kernel 加载内核、-initrd 加载 initramfs,再加一个参数 rdinit=/init 覆盖内核默认行为。

QEMU 启动:`Run /init as init process`,然后打印出「This is a minimal binary」

📷 QEMU 启动:`Run /init as init process`,然后打印出「This is a minimal binary」
回到原视频 (00:56:00)

有意思的是:这个 minimal init 执行 exit 后,内核直接 panic——Attempted to kill init!——「因为你的 init 退出了,整个操作系统就挂掉了。」我们确实控制了 Linux 加载的第一个进程。

2.3 解开真实系统的 initramfs

(参考时间: 00:57)

「我们能解开当前系统的 initramfs 吗?当然可以!」讲师让 AI 去做,过程很有意思——AI 一度「翻车」:

用 AI 解包树莓派真实的 initrd:目录树结构很像你的 `/`

📷 用 AI 解包树莓派真实的 initrd:目录树结构很像你的 `/`
回到原视频 (01:00:00)

编者拓展|「Coding Agent 真正强大的地方」:讲师强调,整个过程中他对具体细节、工具、文件结构「一无所知」,他有的只是最基本的观察(7MB ≠ 23MB)。「AI 可以像人一样探索,只要有足够好的直觉。」解出来的 initrd 里有:启动脚本、NTFS 支持、键盘布局、字体配置、BusyBox 提供的用户空间工具、动态链接库、内核模块与固件驱动——「这就是你磁盘损坏时进入 initrd 模式还能得到命令行体验的原因。」

2.4 pivot_root:切换真实根文件系统

(参考时间: 01:03)

你确信这个 initramfs 是你系统的一部分(内核日志指向它),但你在系统里从没见过它——它到哪去了?

答案是:Linux 启动时,systemd 并不是真正的「一号进程」。在 initramfs 阶段的最后,系统会执行一个系统调用 pivot_root:

int pivot_root(const char *new_root, const char *put_old);
// Changes the root mount in the mount namespace of the calling process.

它重新创造以 systemd 为根的进程树。之后可以 umount 把 put_old 释放。「真实的 Linux:驱动加载、NetworkManager、tty 字体变化……都是在 switch_root 之后由 systemd 拉起的。」

systemd 进程树:`pstree` 展示的整个用户态世界(systemd 是进程树的根)

📷 systemd 进程树:`pstree` 展示的整个用户态世界(systemd 是进程树的根)
回到原视频 (01:04:00)

2.5 亲手点亮

(参考时间: 01:06)

讲师准备的 initramfs 里只有 init 和 bin/busybox(外加必要的驱动)。init 脚本的魔法在于:

# initramfs 阶段的 init
#!/bin/busybox sh
...
for cmd in $(/bin/busybox --list); do
    /bin/busybox ln -s /bin/busybox /bin/$cmd   # 一个文件 = 全套命令
done
mount -t proc proc /proc                        # 创建 procfs 对象
mount -t sysfs sysfs /sys
insmod ...                                      # 安装驱动
mknod /dev/... c/b major minor                  # 创建设备节点
exec /bin/busybox sh                            # 进入交互 shell
手工点亮的起点:`find /` 只有 `/bin/busybox` 和一堆驱动模块

📷 手工点亮的起点:`find /` 只有 `/bin/busybox` 和一堆驱动模块
回到原视频 (01:08:00)

编者拓展|「计算机系统里没有任何魔法」:讲师强调,每一条命令背后都是系统调用——busybox ln -s 背后是 fork + execve + 符号链接系统调用;mkdir 对应创建目录;mount -t proc 把 procfs 的所有对象在 /proc 里创建出来;mknod 创建设备文件,需要指定主设备号/从设备号(如 /dev/random 主 1 从 8、/dev/urandom 主 1 从 9)。「你的 /dev 里每一个文件都是这样创建的。」

挂载磁盘:编辑 /dev/vda(virtio 虚拟磁盘)→ mount -t ext4 /dev/vda /mnt → 里面是另一个文件系统(含网卡驱动和另一个 init)。

VGA 设备点亮:`Goodbye QEMU Console`,图形化终端上一个像素一个像素画出来

📷 VGA 设备点亮:`Goodbye QEMU Console`,图形化终端上一个像素一个像素画出来
回到原视频 (01:16:00)

点亮 Linux 世界:执行 pivot_root 换根后,启动一个 HTTPD 在 8080 端口;QEMU 用 -net user,hostfwd=tcp::8080-:8080 做端口映射,于是在宿主机浏览器里 localhost:8080 就能访问虚拟机里的网页。

端口映射彩蛋:宿主机 `localhost:8080` 访问虚拟机里的 HTTPD(首页 404,说明网络已通)

📷 端口映射彩蛋:宿主机 `localhost:8080` 访问虚拟机里的 HTTPD(首页 404,说明网络已通)
回到原视频 (01:18:30)

「这个 Linux 是真正点亮了。从 initramfs 里只有那一个文件,到加载驱动、pivot_root、启动 HTTPD,再到外面能访问网络服务——所有这些全部都是用系统调用实现的。」

2.6 故事的结尾:应用视角的操作系统

(参考时间: 01:21)


三、应用生态

3.1 是应用生态成就了操作系统的繁荣

(参考时间: 01:22)

厂商、个人开发者每天都在发布新的应用。操作系统不仅需要实现这套 API,还需要一套核心工具集来支撑它们:基本的运行库、coreutils、安装工具、系统管理工具……

应用分发生态的演进:从软盘/光盘到 AppStore / apt / npm / HuggingFace

📷 应用分发生态的演进:从软盘/光盘到 AppStore / apt / npm / HuggingFace
回到原视频 (01:23:00)

3.2 例子:Debian

(参考时间: 01:23)

Our Mission: Creating a Free Operating System. The Debian Project is an association of individuals, sharing a common goal: We want to create a free operating system, freely available for everyone. Now, when we use the word "free", we're not talking about money, instead, we are referring to software freedom.

1998 年的 apt-get install firefox——跨时代的 Advanced Packaging Tool(「苹果 App Store 要到 2000 几年才出来」)。它有一整套开源软件供应链的管理流程:从 unstable(每天往 GitHub 交的代码)→ 测试分支 → 稳定分支。

Debian 的软件供应链:从 unstable 到 testing 再到 stable

📷 Debian 的软件供应链:从 unstable 到 testing 再到 stable
回到原视频 (01:24:00)

Debian 软件包(deb)就是一个压缩包:

组成部分 内容
control.tar.xz control 文件:Package、Source、Version、Architecture、Maintainer、Depends、Suggests、Section、Priority、Description……
data.tar.xz 实际的文件(绝对路径)

dpkg 可以安装 deb 包——它也是操作系统上的一个普通应用程序(使用系统调用完成「安装」功能)。

编者拓展|软件供应链的安全:安装一个 deb 包的流程是 Preinstall & Unpack → Configure → Triggers → Postinstall。讲师警告:postinstall hook 能偷走你的一切——「最近 axios(每周下载量超 3 亿次)被投毒了。」这就是为什么「一个安全漏洞就能把整个系统拖垮」。

3.3 AI 时代:应用生态的变化

(参考时间: 01:25)

AI 时代的接口变化:应用会退化为「工具」和「服务」吗?

📷 AI 时代的接口变化:应用会退化为「工具」和「服务」吗?
回到原视频 (01:25:30)


总结


附:官方参考与延伸阅读

本讲的讲义见课程主页,以下链接按书中出现顺序整理:

主题 链接
Ritchie, The Evolution of the UNIX Time-sharing System https://read.seas.harvard.edu/~kohler/class/aosref/ritchie84evolution.pdf
同上(jyywiki 导读版) https://jyywiki.cn/OS/2026/ritchie84evolution.md
Minix 项目 http://minix3.org
Minix(虚拟化演示) https://jyywiki.cn/OS/demos/virtualization/minix
Minix 1 & 2 存档(Quick and Dirty editions) https://github.com/davidgiven/minix2
最小 Linux(linux-minimal) https://jyywiki.cn/OS/demos/virtualization/linux-minimal
Linux(虚拟化演示) https://jyywiki.cn/OS/demos/virtualization/linux
The kernel's command-line parameters https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html
BusyBox https://git.busybox.net/busybox/tree/busybox?h=1_01
Rosenblatt, The Perceptron(1958) https://homepages.math.uic.edu/~lreyzin/papers/rosenblatt58.pdf
Linus vs Tanenbaum 论战全文 https://www.oreilly.com/openbook/opensources/book/appa.html
LiMOS: NOILinux Lite(switch_root 之后) https://zhuanlan.zhihu.com/p/619237809
caveman https://github.com/JuliusBrussee/caveman
A2UI: A Protocol for Agent-Driven Interfaces https://a2ui.org/

阅读材料:强烈推荐读 Ritchie 的 Evolution of the UNIX Time Sharing System;并在自己的 Linux 上动手解包 initrd、观察 pivot_root 前后的世界。

版权说明:本讲讲义与幻灯片作者为蒋炎岩,采用 Creative Commons BY-NC 4.0 许可,来源于 https://jyywiki.cn/OS/2026/。视频画面与字幕版权归原作者所有。本书为课堂内容的学习性重构。