Linux 系统
一台机器,几百个程序同时运行,共享同一块内存、同一组磁盘、同一张网卡——这在物理上是不可能的,但它每天都在发生。Linux 的工作,是在硬件和程序之间制造一系列精心设计的幻觉,同时让这些幻觉对所有人都显得真实可靠。
这个系列分两个层次:
概念层(01-13):理解 Linux 是什么——每个抽象为什么存在,为什么这样设计,不这样设计会怎样。
专题层(T1-T7):遇到问题怎么办——以 SOP 为主,实际操作为核心,直接可用的手册。
两个层次互相支撑:理解概念层,专题层的操作才有根基,知道为什么而不只是知道怎么做;掌握专题层,概念层的抽象才有落地,知道在哪里用而不只是知道有什么。
二、概念线索
这是整套系列的核心:20 篇文章里反复出现的五条思想脉络。 读懂这五条线索,就抓住了 Linux 设计哲学的骨架。
mindmap root((Linux 系统)) 抽象层 进程 虚拟CPU独占 内存 虚拟地址空间 文件 一切皆文件 控制层 权限 最小权限原则 系统调用 内核边界 生命周期 启动 引导链条 服务 声明式管理 接口层 Shell 进程编排 包管理 依赖契约 对外连接 网络 协议栈抽象 存储 持久化层次 可观测性 系统自述
线索一:「一切皆文件」——用同一个接口统一不同的东西
这不只是一个设计决定,是一种哲学主张:不同性质的东西,如果行为足够相似,就用同一套接口对待,让差异沉入抽象层之下。
- inode 把名字和内容分离(04-文件:把不同的东西变成同一件事):文件名是目录里的条目,inode 才是文件的真身。一个内容可以有多个名字(硬链接),名字消失内容还在(unlink 的语义)。
- VFS 统一所有文件系统(04-文件:把不同的东西变成同一件事):ext4、NFS、tmpfs、procfs——对进程来说都是
open()/read()/write(),VFS 在背后做翻译。 /proc/sys把内核状态变成文件(04-文件:把不同的东西变成同一件事 / 13-可观测性:系统如何记录自己):cat /proc/meminfo就是在读内核的内存计数器,内核把自己的运行状态输出成文件树,任何工具都能读。- socket 把网络连接变成 fd(11-网络:Linux 的网络模型):
socket()返回整数,之后read()/write()/close()同样适用。TCP 的三次握手、拥塞控制、重传——全部在内核里,对进程透明。 - 管道是匿名文件(09-Shell:Linux的母语):
ls | grep中间的|是一个内核对象,两个进程各持有它的一端,用read()/write()通信。
这条线索的终点:所有的 read() / write() 调用,无论操作的是磁盘文件、网络连接、内核接口还是进程间管道,背后都是同一套系统调用,同一套内核接口抽象。
线索二:「最小权限」——只给完成任务所需的最少能力
这是安全工程的第一原则,也是 Linux 权限体系从粗粒度到细粒度演化的内在逻辑。
- UID 作为整数身份(05-权限:身份是一个整数):内核不认识用户名,只认识数字。UID 0 就是 root,这个设计极简但有效。
- capabilities 把 root 一分为多(05-权限:身份是一个整数 / T4-安全专题):
CAP_NET_BIND_SERVICE允许绑定低端口,CAP_SYS_PTRACE允许调试进程——不再需要完整 root,按需授权。 - 系统调用作为唯一合法的内核入口(06-系统调用:内核与用户空间的边界):用户程序不能直接操作硬件,所有特权操作必须通过系统调用请求内核代劳,内核是最后的仲裁者。
- seccomp 过滤系统调用(06-系统调用:内核与用户空间的边界 / T4-安全专题):即使程序被攻破,seccomp 限制它能使用的系统调用,把损害限制在沙箱内。
- AppArmor / SELinux 强制访问控制(T4-安全专题):即使以 root 运行,MAC 策略限制程序能访问哪些文件和网络——DAC 之上的额外一层。
- systemd 的安全隔离选项(08-服务:进程的社会契约 / T2-系统管理):
NoNewPrivileges=true、CapabilityBoundingSet=、DynamicUser=true——声明式地约束服务的权限边界。
这条线索的终点:从 UID 到 capabilities 到 seccomp 到 MAC,是最小权限原则在不同粒度上的实现,粒度越来越细,攻击面越来越小。
线索三:「声明式 > 命令式」——描述想要什么,而不是怎么做
命令式:执行这些步骤。声明式:这是我想要的状态,你去实现并维持它。Linux 的配置体系正在从命令式向声明式演进。
- systemd unit 文件(08-服务:进程的社会契约 / T2-系统管理):描述服务应该运行、依赖谁、资源限制是什么——systemd 负责启动、监控、崩溃重启,持续维持声明的状态。
- iptables / nftables 规则(11-网络:Linux 的网络模型 / T3-网络专题):写规则描述”哪些包应该被允许/拒绝”,内核在每个数据包经过时执行这些规则,不需要程序持续运行。
/etc/fstab(12-存储:持久化的代价 / T5-存储专题):描述哪个设备应该挂载到哪里,系统启动时自动实现。- Ansible playbook(T2-系统管理):描述目标系统状态,幂等执行——多次运行结果相同,而不是多次执行多次操作。
这条线索的终点:写规则,不写过程。声明式配置的优势是可审计(配置即文档)、可重现(相同声明得到相同状态)、可维持(系统持续收敛到声明状态)。
线索四:「可观测性」——系统如何让自己可被理解
一个无法被观测的系统,出问题只能靠猜。Linux 从设计上就有让自己可被观测的机制,从最基础的文件读取到最现代的 eBPF 插桩。
/proc/sys是内核的实时自述(04-文件:把不同的东西变成同一件事 / 13-可观测性:系统如何记录自己):cat /proc/meminfo、cat /sys/block/sda/stat——内核把运行状态写成文件,任何工具都能读取,没有特权 API。- 系统调用边界是天然的观测点(06-系统调用:内核与用户空间的边界 / T7-开发者工具):所有用户程序和内核的交互都经过系统调用,
strace在这里拦截,就能看到程序的所有行为。 - journald 集中记录事件序列(13-可观测性:系统如何记录自己 / T2-系统管理):结构化存储,按服务/优先级/时间精确过滤——是排查问题的时间机器。
- eBPF 在内核路径上精确插桩(06-系统调用:内核与用户空间的边界 / T6-性能调优):不修改应用、不重启服务,在内核的任意位置挂载探针,收集延迟分布、调用路径、资源竞争——几乎零开销。
- perf 和火焰图(T6-性能调优 / T7-开发者工具):把 CPU 时间的分布可视化,把”我感觉慢”变成”第 42 行的字符串格式化占了 35% 的 CPU”。
这条线索的终点:从 cat /proc/meminfo 到 bpftrace,都是在把不可见的变得可见。可观测性不是事后加的功能,是 Linux 设计的一部分。
线索五:「分层抽象」——每层只与相邻层说话,独立演进
复杂系统的可维护性来自层次的清晰:每一层对下层的实现保持无知,只依赖接口。这让每层可以独立替换和演进。
- VFS 统一文件系统接口(04-文件:把不同的东西变成同一件事):HTTP/3 换掉了 TCP,HTTP 语义不变——因为 HTTP 不关心传输层的实现,只依赖接口。
- TCP/IP 协议栈分层(11-网络:Linux 的网络模型 / T3-网络专题):应用层不关心传输层,传输层不关心网络层——每层对下层保持无知,换取下层的接口契约。
- LVM 解耦物理与逻辑边界(12-存储:持久化的代价 / T5-存储专题):文件系统不知道数据在哪块物理磁盘上,LVM 在中间做映射——在线扩容、迁移、快照都在这层完成。
- 容器的命名空间隔离(11-网络:Linux 的网络模型 / T3-网络专题 / T4-安全专题):每个容器有自己的网络栈、文件系统视图、进程空间——通过 namespace 在同一内核上隔离出独立的环境。
- 包管理的依赖抽象(10-包管理:软件边界与依赖契约):每个包声明依赖接口(版本约束),不关心具体实现——SemVer 是层间接口契约的社会化版本。
这条线索的终点:分层不是为了模块化,是为了让每层可以独立演进。理解这个,才能理解为什么 Linux 可以在不改变应用的情况下替换底层实现。
三、概念系列(01–13)
起点:操作系统在解决什么问题
核心问题:为什么需要操作系统这个中间层? 读完之后:理解”资源竞争”和”抽象”是操作系统存在的两个根本理由。
- 01-操作系统在解决什么问题 — 硬件稀缺、程序贪婪、操作系统作为仲裁者
第一层:抽象——Linux 如何把硬件变成对程序友好的世界
硬件是粗粝的。这三篇文章解释 Linux 如何把 CPU / 内存 / 存储设备,变成”每个程序独占 CPU""我有足够内存""文件就在那里”这三个幻觉。
-
02-进程:被虚构的独占感 核心问题:CPU 一次只能做一件事,多个程序怎么同时运行? 关联:→ 08-服务:进程的社会契约(服务是有监管的进程)→ 09-Shell:Linux的母语(shell 是进程编排器)→ T1-故障排查(进程崩溃排查)
-
03-内存:每个程序都以为自己拥有全部 核心问题:物理内存有限,虚拟地址空间无限,这个矛盾如何解决? 关联:→ T6-性能调优(Huge Pages、NUMA)→ T7-开发者工具(内存错误检测)→ T1-故障排查(OOM 排查)
-
04-文件:把不同的东西变成同一件事 核心问题:磁盘文件、网络连接、内核接口、进程间管道,为什么都能用 read()/write() 操作? 关联:→ 11-网络:Linux 的网络模型(socket 是文件的延伸)→ 13-可观测性:系统如何记录自己(/proc /sys 是文件)→ 12-存储:持久化的代价(挂载机制)
第二层:控制——Linux 如何决定谁能做什么
多个程序共享资源,必须有人划定边界。Linux 用两道边界:进程之间(权限),内核和用户之间(系统调用)。
-
05-权限:身份是一个整数 核心问题:Linux 怎么知道”谁”在操作?怎么决定”能不能”? 关联:→ T4-安全专题(capabilities、MAC)→ T2-系统管理(sudo、SSH)→ 08-服务:进程的社会契约(DynamicUser、CapabilityBoundingSet)
-
06-系统调用:内核与用户空间的边界 核心问题:为什么程序不能直接操作硬件?一次 read() 到底发生了什么? 关联:→ T7-开发者工具(strace 在系统调用边界拦截)→ T6-性能调优(eBPF 在系统调用上插桩)→ T4-安全专题(seccomp 过滤系统调用)
第三层:生命周期——Linux 如何管理时间
系统有生命周期:从一台冷机器引导成运行中的系统,再到服务的启动、运行、崩溃、重启。
-
07-启动:一台死机器如何引导自己活过来 核心问题:按下电源键,到完整的 Linux 系统,中间发生了什么? 关联:→ 08-服务:进程的社会契约(systemd 是启动的终点)→ 12-存储:持久化的代价(initramfs 解决根文件系统的鸡蛋问题)
-
08-服务:进程的社会契约 核心问题:服务和进程有什么区别?systemd 的设计哲学是什么? 关联:→ T2-系统管理(unit 文件编写实战)→ T1-故障排查(服务启动失败排查)→ T4-安全专题(systemd 安全隔离选项)
第四层:接口——人如何与 Linux 对话
前三层是 Linux 内部的世界,这一层是人与系统的接触面:Shell 是人与内核的翻译官,包管理解决软件如何共存。
-
09-Shell:Linux的母语 核心问题:Shell 是什么?管道为什么是 Unix 最重要的发明? 关联:→ T2-系统管理(Shell 脚本自动化)→ T1-故障排查(Shell 是排查工具的载体)→ 06-系统调用:内核与用户空间的边界(每个命令是一次 fork/exec)
-
10-包管理:软件边界与依赖契约 核心问题:依赖地狱的根本原因是什么?不同包管理哲学的取舍是什么? 关联:→ T2-系统管理(apt/dnf 日常维护)→ T7-开发者工具(动态库与链接机制)
第五层:对外连接与可观测性
系统与外部世界的接口,以及系统对自身状态的记录。
-
11-网络:Linux 的网络模型 核心问题:Linux 如何看待网络?socket 抽象的本质是什么? 关联:→ T3-网络专题(防火墙、容器网络、VPN、DNS 深入)→ T1-故障排查(网络故障排查)→ T4-安全专题(Netfilter 与防火墙)
-
12-存储:持久化的代价 核心问题:write() 成功了,数据一定在磁盘上吗?Linux 的存储抽象层次是什么? 关联:→ T5-存储专题(LVM、RAID、备份、NFS 深入)→ T1-故障排查(存储故障排查)→ T6-性能调优(磁盘 I/O 调优)
-
13-可观测性:系统如何记录自己 核心问题:/proc 和 /sys 是什么?如何从外部推断系统内部状态? 关联:→ T1-故障排查(排查工具的基础)→ T6-性能调优(perf、eBPF)→ T7-开发者工具(strace、gdb)
四、专题系列(T1–T7)
概念系列回答”是什么、为什么”,专题系列回答”遇到问题怎么办”。 每个专题以 SOP 和实操为主,哲学思考只作开篇定调。
T1 故障排查
什么时候打开:服务不可用 / 连不上网络 / 磁盘满 / 进程崩溃 / 系统响应慢
覆盖四类高频故障:网络不通(五层诊断法)/ 存储异常(磁盘满、inode 耗尽、I/O 慢、文件系统损坏)/ 性能瓶颈(CPU/内存/I/O wait 的漏斗模型)/ 进程与服务(退出码判断、OOM、死锁、端口冲突)
T2 系统管理
什么时候打开:需要编写 systemd 服务 / 配置定时任务 / 管理用户权限 / 加固 SSH / 调整内核参数
覆盖:systemd unit 文件编写(Type、依赖、资源限制、安全隔离)/ 定时任务(.timer)/ journald 查询与配置 / sudo 策略 / SSH 加固 SOP / sysctl 持久化 / Ansible 自动化入门
T3 网络专题
什么时候打开:防火墙规则不生效 / 容器网络断了 / 需要配置 VPN / DNS 解析失败 / 端口转发不通
覆盖:iptables/nftables 完整基线配置(含脚本)/ nftables 迁移 / NAT 与端口转发 / Docker 四种网络模式 / 自定义网络与 Compose / WireGuard 点对点与星型拓扑 / DNS 解析链与 systemd-resolved / dnsmasq
T4 安全专题
什么时候打开:服务器加固 / 审计 SUID 文件 / 配置 AppArmor/SELinux / 排查安全事件 / 容器安全加固
覆盖:系统最小化 / 内核安全 sysctl / fail2ban / SUID 审计 / AppArmor profile 编写与排查 / SELinux AVC 排查与修复 / auditd 规则配置 / AIDE 文件完整性监控 / 容器安全(非 root、只读根文件系统、capabilities、seccomp)
T5 存储专题
什么时候打开:LVM 扩容 / 磁盘迁移 / 配置 RAID / 建立备份策略 / 配置 NFS 共享
覆盖:LVM 完整规划与创建 / 在线扩容 SOP / 快照与一致性备份 / pvmove 磁盘迁移 / mdadm RAID 创建与磁盘替换 SOP / rsync 硬链接快照备份 / Restic 现代备份工具 / 备份验证 SOP / NFS 与 Samba 配置
T6 性能调优
什么时候打开:系统慢找不到原因 / 需要建立性能基准 / 调优内核参数 / 使用 eBPF 分析
覆盖:fio 磁盘基准测试(四个核心场景)/ iperf3 网络测试 / CPU 亲和性与 NUMA / sysctl 内存与网络参数 / Huge Pages / I/O 调度器 / TCP BBR / bpftrace 语法与常用一行命令 / BCC 工具集 / perf 与火焰图生成
T7 开发者工具
什么时候打开:程序崩溃找不到原因 / 内存错误排查 / 找性能热点 / 动态库链接问题
覆盖:动态库查找路径(RPATH/LD_LIBRARY_PATH/ldconfig)/ ldd、nm、readelf 分析二进制 / 常见链接错误排查 / gdb 完整命令速查 / AddressSanitizer 内存错误检测 / Valgrind / perf 采样分析与火焰图 / strace 高级用法与系统调用解读
五、按场景的阅读路径
不同目的的人,从不同的地方开始。
路径一:第一次系统学 Linux
按概念系列的顺序,每篇建立在前一篇的基础上:
01(为什么需要 OS)
→ 02(进程:CPU 分时)
→ 03(内存:虚拟地址空间)
→ 04(文件:一切皆文件)
→ 05(权限:身份与边界)
→ 06(系统调用:内核边界)
→ 07(启动:系统如何活过来)
→ 08(服务:进程的监管)
→ 09(Shell:进程编排语言)
→ 10(包管理:软件依赖契约)
→ 11(网络:协议栈与 socket)
→ 12(存储:持久化代价)
→ 13(可观测性:系统自述)路径二:运维 / SRE(快速上手)
先理解核心机制,直接进入实操:
01(OS 在解决什么问题,建立心智模型)
→ 08(服务管理,日常工作基础)
→ 13(可观测性,排查工具基础)
→ T1(故障排查,高频场景手册)
→ T2(系统管理,日常运维手册)
→ T3(网络专题,按需深入)
→ T4(安全专题,加固合规)路径三:开发者(理解底层)
关注程序和内核交互的机制:
01(OS 存在的理由)
→ 02(进程模型,fork/exec/wait)
→ 03(内存模型,虚拟地址空间)
→ 06(系统调用,内核边界)
→ 04(文件接口,一切皆文件)
→ 09(Shell,进程编排)
→ T7(开发者工具:gdb/ASan/perf)
→ T6(性能调优:基准/eBPF/火焰图)路径四:线上问题紧急排查
T1(故障排查)直接定位问题类型
→ 13(可观测性)找到观测数据
→ 对应专题(T3/T5/T6)深入解决路径五:容器 / 云原生方向
02(进程与 namespace 的关系)
→ 06(系统调用,seccomp 基础)
→ 11(网络模型,容器网络基础)
→ T3(网络专题:容器网络、Netfilter)
→ T4(安全专题:容器安全加固)
→ T5(存储专题:卷和网络文件系统)路径六:安全加固方向
05(权限:身份与最小权限原则)
→ 06(系统调用:seccomp 机制)
→ 08(服务:systemd 安全隔离)
→ T4(安全专题:完整加固手册)
→ T2(系统管理:SSH、sudo、审计)
→ T3(网络专题:防火墙基线)六、延伸方向
这个系列聚焦于 Linux 作为操作系统的理解与使用。以下方向与本系列相关,但各自构成独立的学习领域:
-
Linux 内核开发:内核源码、驱动开发、内核模块编写,门槛较高,需要单独成系列。起点:
drivers/目录 + LDD3(Linux Device Drivers)。 -
网络协议深入:TCP/IP 协议栈的数学原理(Nagle 算法、拥塞窗口、BBR 推导),见
15-computing/40-systems/40-networking/。 -
容器与虚拟化:Docker 源码、containerd、runc,Kubernetes 调度器,见相关系列。本系列的 T3/T4 提供了理解容器网络和安全的内核基础。
-
云原生可观测性:Prometheus、Grafana、OpenTelemetry——建立在本系列第 13 篇(可观测性)和 T6(eBPF)的基础上。
-
系统编程:用 C/Rust 直接调用系统调用,理解 POSIX 标准,见 APUE(Advanced Programming in the Unix Environment)。本系列第 06 篇(系统调用)是入口。