【操作系统百科】内存回收
Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。
发布来自土法炼钢兴趣小组的知识、笔记、进展和应用。主题包括数据结构和算法、编程语言、网络安全、密码学等。
共 111 篇文章 · 返回首页
Linux 内存回收是 VM 最复杂的子系统之一。本文讲 active/inactive LRU、kswapd 与 direct reclaim、watermark 三线、swappiness 的真实含义、MGLRU 改造、memcg 回收与 PSI。
swap 还值得开吗?本文讲 swap area 基础、swap cache、zram 压缩内存、zswap 前端压缩池、swappiness 的真实含义、容器里的 swap 策略,以及为什么现代 Android 全靠 zram 不靠磁盘。
buddy 只管页粒度(4K+),内核大多数对象只有几十到几百字节。slab/SLUB 在 buddy 之上做对象级缓存。本文讲 slab 历史、SLUB 接手、SLOB 退场、kmem_cache、per-CPU cache、KASAN 集成。
glibc malloc、tcmalloc、jemalloc、mimalloc 各有哲学。本文讲 arena、thread cache、size class、madvise 返还策略、碎片与 RSS 膨胀、如何根据负载选分配器。
io_uring 用共享内存 ring buffer 实现零 syscall 异步 I/O——SQ/CQ、SQPOLL、IOPOLL、注册 fd/buffer、multishot、安全模型演化。本文深入内核实现与工程实践。
splice 在内核 pipe buffer 间移动数据——不经过用户态。本文讲 splice/tee/vmsplice 原理、pipe_buffer 与 page 生命周期、sendfile 的前世、CVE-2022-0847 Dirty Pipe 复盘。
READ_ONCE、smp_mb、smp_store_release——内核并发代码的基石。本文讲 LKMM 的诞生、ordering 语义、cumulativity、address/data/control 依赖、marked vs plain access、litmus test 方法论。
x86 LOCK 前缀、ARM LL/SC、ARMv8.1 LSE、RISC-V A 扩展——四种硬件原子原语的工程差异。本文讲 fetch_add/CAS/swap 成本、cache line bouncing、tearing 与内核 atomic API。
BPF 为什么能成为 Linux 的第二用户态?verifier、JIT、map 家族、BTF、CO-RE、BPF_LSM、sched_ext——本文讲 eBPF 的内核侧机制。
BSD 的哪些决定值得 Linux 借鉴?kqueue vs epoll、jail vs namespace、ZFS 一等公民、DTrace、pledge/unveil、网络栈差异——本文对照 BSD 与 Linux 的关键取舍。
NT 内核与 Linux 的根本差异——Executive/Kernel 分层、object manager、IRP I/O 模型、Job object、IOCP、Registry、WSL2 的选择。
VxWorks/QNX/Zephyr 与 Linux PREEMPT_RT 的工程取舍——硬实时 vs 软实时、静态调度、ARINC-653 分区、安全认证(DO-178C)、最小内存占用。
Unikernel 在云上为什么没成主流?MirageOS、IncludeOS、Unikraft、OSv 的设计取舍——库操作系统、启动时间、工具链、调试困难、POSIX 兼容。
Rust for Linux 真的在解决问题还是在搬问题?合入时间线、抽象 crate、Pin/unsafe 边界、Asahi GPU 驱动、维护成本、ABI 兼容、工具链依赖。
OS 如何在不信任 hypervisor 的世界里自处?AMD SEV-SNP、Intel TDX、ARM CCA、远程认证(attestation)、COCONUT-SVSM、Guest Firmware、I/O 加密。
CXL/RDMA 会把 OS 拆成什么形状?LegoOS 分离式内核、CXL 2.0/3.0 内存池、Far Memory、远程页面错误、failover 语义——本文讲硬件解耦对 OS 的冲击。
下一代 OS 应为 AI workload、异构计算、CXL、内核旁路做什么?加速器主导的调度、sched_ext + ML、分离执行、OS 与 runtime 的重新分工——以工程案例收束全系列。
容器 vs 虚机 vs microVM 的真实隔离差距。namespace+cgroup+seccomp+capabilities 组合、user namespace rootless、gVisor、Kata Containers、Firecracker——本文评估容器安全。
VM-exit/VM-entry 的代价和近年优化。VMX/SVM 硬件虚拟化、EPT/NPT 二级页表、APICv posted interrupts、vCPU 调度、nested virtualization——本文讲 x86 虚拟化基础。
KVM 在 Linux 中如何做到最小的 hypervisor?/dev/kvm ioctl、QEMU 用户态设备模型、vhost-net/vhost-user、virtio、eventfd/irqfd、IOMMU、SEV/TDX 集成。
为什么 setuid root 早该被 capabilities 取代?cap sets(permitted/effective/inheritable/bounding/ambient)、file caps、容器内 capabilities——本文讲 Linux 的细粒度权限模型。
进程自限如何实现最小权限?seccomp strict mode、filter mode(BPF 过滤器)、user notify、Landlock 文件访问控制、syscall user dispatch——本文讲 Linux 的系统调用过滤。
SELinux 与 AppArmor 的模型差异如何影响运维?LSM hooks、类型强制策略、AppArmor profile、permissive/enforce 模式、容器标签——本文讲 Linux 强制访问控制。
从引导到运行时的完整性保证链如何闭环?measured boot → IMA measurement/appraisal → EVM → dm-verity / fs-verity → TPM PCR——本文讲 Linux 的完整性子系统。
Spectre/Meltdown 时代留给内核的性能税有多重?KASLR、KPTI、retpoline、IBRS/eIBRS、RSB stuffing、SSBD——本文讲 CPU 漏洞缓解措施的内核实现。
ftrace 是 Linux 内核的内置追踪框架——函数追踪、function graph、tracepoints、trace-cmd。本文讲 mcount/fentry 机制、动态 patching、histogram、synthetic events。
perf 到底看到了什么?PMU 硬件计数器、tracepoint、perf_event_open、perf ring buffer、Processor Trace——本文讲 perf 子系统的内核机制。
kprobe/uprobe/fprobe 在热点路径的真实 overhead 是多少?本文讲 int3 断点机制、fprobe 基于 ftrace 的优化、uprobe 用户态探针、USDT、BPF 联动。
线上 panic 如何留下可分析的证据?kexec 启动捕获内核、crashkernel 参数、vmcore 分析、crash 工具、ramoops/pstore——本文讲 Linux 的故障转储机制。
lockdep 报的 ABBA 死锁该不该怕?本文讲 lockdep 锁依赖追踪、lockdep_assert_held、KCSAN 并发检查、KFENCE 内存越界检测、false positive 处理。
printk 还能活多久?printk 缓冲区、dev_printk、rate limiting、netconsole、printk lockless 改造——本文讲内核日志子系统的机制与演化。
为什么 /proc/self/status 的字段总让人困惑?本文讲 procfs vs sysfs 设计哲学、常用字段解读、pid namespace 下表现、per-cgroup 接口、稳定性分级。
按下电源键到看到登录界面——中间经历了固件、bootloader、内核解压、start_kernel、rest_init、PID 1。本文走一遍 x86 和 ARM 的完整启动时间轴。
现代 Linux 启动离不开 initramfs——加密 root、LVM、NVMe 驱动都在 initramfs 加载。本文讲 cpio 归档、early userspace、dracut 模块化、switch_root、unified kernel image(UKI)。
execve 之后,内核把 ELF 二进制搬上场——PT_LOAD 段 mmap、动态链接器 ld.so、GOT/PLT 延迟绑定、PIE、aux vector。本文走完从 execve 到 main 的全路径。
vDSO 把 gettimeofday/clock_gettime 搬到用户态——零 syscall 读时间。本文讲 vDSO 原理、vvar 共享页、getrandom vDSO、x86/arm64 差异、vsyscall 退役、time namespace 支持。
out-of-tree 模块在现代 Linux 还该不该存在?本文讲模块加载机制、符号版本(modversions)、Secure Boot 签名、DKMS、lockdown、module taint、livepatch(kpatch/kGraft)。
sysctl/sysfs/tracefs 哪些能依赖?syscall 反而最稳定。本文讲 Documentation/ABI 框架、sysfs 规则、debugfs/tracefs 非承诺、Linus 的 never break userspace 规则与例外。
从硬件信号到 handle_irq——中断的全旅程。本文讲 IDT、APIC/x2APIC、MSI/MSI-X、GSI 到 IRQ 映射、irq_desc、affinity 绑定、IPI、中断风暴与重平衡。
中断下半部有三条路——softirq(静态编号、高性能)、tasklet(动态但退役中)、workqueue(可睡眠、灵活)。本文讲三者实现、ksoftirqd 切换、threaded NAPI、workqueue 类型与调优。
把 IRQ handler 线程化——PREEMPT_RT 的核心改造之一。本文讲 request_threaded_irq、handler/thread_fn 分工、IRQF_ONESHOT、全线程化的延迟与吞吐代价、softirq 线程化趋势。
从 jiffies 时代的 timer wheel 到纳秒精度的 hrtimer——Linux 定时器的两套体系。本文讲 timer wheel 层次、hrtimer 红黑树实现、clock_event_device、slack 与 coalescing、定时器迁移。
NO_HZ_FULL 让 CPU 运行用户态时不受 tick 打断——数据库、DPDK、低延迟交易的利器。本文讲 NO_HZ_IDLE/FULL、housekeeping CPU、RCU nocb、isolcpus、副作用与实际配置。
TSC 真的稳吗?本文讲 clocksource/clockevents 分离、TSC invariant/unstable 判定、HPET/ACPI PM/arch_timer、watchdog 校准、vDSO gettimeofday、PTP/PHC 硬件时间戳。
云环境和虚拟化里,CPU 可以运行时上下线。本文讲 CPUHP 状态机、cpu_up/cpu_down 路径、RCU 和定时器迁移、锁竞争、nohz_full 与热插拔的陷阱、回归事故案例。
suspend-to-idle、S3 suspend、hibernate——三种系统级休眠的工程差异。本文讲 runtime PM、system PM、freeze_kernel、pm_qos、设备树/ACPI 配合、笔记本与服务器场景差异。
内核 spinlock 从关中断到 qspinlock 演化了四代。本文讲原始 spinlock、ticket lock、MCS lock、qspinlock、paravirt qspinlock、spin_lock_irqsave 的代价与 NUMA 友好性。
内核 mutex 先自旋再睡眠——adaptive spin 策略。本文讲 mutex 实现、MCS wait list、owner handoff、rwsem 公平与不公平、PREEMPT_RT 替换、lockdep 死锁检测。
RCU 是 Linux 内核使用最广泛的同步机制——读侧零开销。本文讲经典 RCU、Tree RCU、Tasks RCU、SRCU、grace period、rcu_dereference、call_rcu、lazy RCU、nocb CPU。
seqlock 让读者无锁重试——写者递增序列号,读者检测到变化则重试。本文讲 seqcount/seqlock 区别、write_seqlock 语义、timekeeper 用法、与 RCU 对比、load tearing 风险。
高频 refcount 每次 inc/dec 都是 cache line bouncing。percpu_refcount 用 per-CPU 计数器解决——活跃时零竞争,关闭时收敛为原子。本文讲两阶段设计、SRCU、kref 与正确关闭顺序。
glibc pthread_mutex 背后是 futex——用户态快路径无 syscall,竞争时才进内核。本文讲 FUTEX_WAIT/WAKE、PI futex、robust futex、futex2、requeue、安全补丁与工程陷阱。
火星探路者号因优先级反转重启——这是实时系统最经典的故事。本文讲优先级反转现象、PIP 优先级继承协议、PCP 优先级天花板、rt_mutex、PREEMPT_RT 的 spinlock 转换、DEADLINE 任务反转。
用 herd7 跑 litmus test、用 CBMC 检查有界模型、用 TLA+ 验证协议——内核并发代码的形式化验证实践。本文讲工具链、实际 bug 案例、与传统测试的权衡。
一次 read(fd, buf, n) 从用户态到磁盘要穿过多少层?本文追踪 VFS read/write 全路径——file_operations、iter_iov、iomap、页缓存命中与 miss、直接 I/O 旁路、块层提交、fsnotify 插桩。
Linux 有两套异步 I/O——glibc POSIX AIO(线程池伪装)和内核 libaio(io_submit/io_getevents,限制重重)。本文讲两者实现、O_DIRECT 约束、io_cancel 不可用性、与 epoll 的不可组合问题。
epoll 用红黑树管理 fd、就绪链表 O(1) 返回事件——打败 select/poll 的关键。本文讲 eventpoll 结构、LT/ET 语义、EPOLLEXCLUSIVE 与惊群、级联 epoll、EPOLLONESHOT、与 io_uring 的比较。
select 和 poll 是最古老的 I/O 多路复用——O(n) 扫描、fd_set 1024 上限、每次 copy 全部集合。本文讲它们的实现、ppoll 信号安全、pselect、嵌入式与 POSIX 兼容场景下的残留价值。
Linux 把信号、事件、定时器、进程都变成 fd——signalfd/eventfd/timerfd/pidfd。本文讲每种 fd 的用途、与 epoll 组合、KVM 的 eventfd、systemd 的 pidfd、以及 fd 化哲学。
epoll、io_uring、libaio、阻塞线程池——四种异步模型的真实性能对比。本文用统一 workload 量化 echo server、静态文件服务、数据库 I/O 场景下的吞吐、延迟与 CPU 开销。
Linux 的一切皆文件靠 VFS 实现——superblock、inode、dentry、file 四层抽象加 ops 表。本文讲 VFS 核心数据结构、dcache、inode cache、RCU lookup,以及文件系统如何插入 VFS。
/a/b/c 如何变成 inode 指针?本文讲 namei 的 LOOKUP_RCU 快速路径、mount 穿越、symlink loop 保护、openat2 的 RESOLVE_* 安全标志、case-insensitive 扩展。
fd 是用户态访问文件的句柄——但 fd 的共享语义在 fork/exec/dup/CLOEXEC 下极其微妙。本文讲 files_struct、fdtable、close_range、pidfd_getfd、cloexec 默认化趋势。
POSIX fcntl 锁为什么在 2025 年还这么坑?本文讲 flock(BSD 锁)、POSIX fcntl 锁、OFD 锁(F_OFD_SETLK)、NFS lockd、lease——以及 POSIX 锁的 fork/close 语义陷阱。
扩展属性(xattr)是 inode 的元数据扩展点——POSIX ACL、capability set、SELinux label 都存在 xattr 里。本文讲 xattr 四命名空间、POSIX ACL、文件 capability、备份工具与容器镜像的 xattr 问题。
监控文件变化的三代方案 dnotify/inotify/fanotify 都不完美。本文讲内核 fsnotify 架构、inotify 的限制、fanotify FAN_REPORT_FID 与内容拦截、audit 联动、高频场景的 overflow 问题。
OverlayFS 用 lower/upper/work 三层实现联合挂载——容器镜像层栈的内核根基。本文讲 copy_up、whiteout、opaque、metacopy、redirect_dir、性能与 Docker overlay2 驱动的工程细节。
FUSE 把文件系统实现搬到用户态——开发快、崩溃不影响内核。本文讲 FUSE 协议、/dev/fuse 通信、FUSE_PASSTHROUGH、virtio-fs、io_uring FUSE、性能天花板与优化策略。
Buddy 是 Linux 物理页分配的底座——用二的幂次空闲链表管理所有物理页。本文讲 buddy 算法、zone 划分、gfp flags、per-CPU page 热路径、碎片与 compaction 的关系。
内核需要大片虚拟连续但物理不连续的内存时用 vmalloc;需要映射 I/O 寄存器时用 ioremap;kmap 曾是 HIGHMEM 的桥梁。本文讲 vmalloc 区域、vmap、ioremap 与 PAT、kmap_atomic 的退役。
per-CPU 变量是内核可扩展性的核心武器——每 CPU 一份副本,读写无锁。本文讲静态 per-CPU、dynamic per-CPU chunk、this_cpu_* 操作、percpu_counter、preempt 与 per-CPU 的微妙关系。
内核内存 bug 是最难追的:UAF、OOB、double free、leak 都可能沉默数月。本文讲 KASAN 三种模式、KFENCE 生产采样、kmemleak、SLUB_DEBUG、UBSAN/KCSAN 联动。
虚拟内存是现代 OS 最核心的抽象:每个进程都像独占一块连续大内存。本文讲 VM 到底给了什么、代价是什么——VA/PA 映射、保护、隔离、COW、mmap 语义、overcommit、地址空间布局。
x86_64 默认 4 级分页(PML4),Linux 4.14+ 支持 5 级(LA57)。本文讲清各级索引、PTE bit、CR3 切换、PCID/INVPCID,以及硬件 page walker 为什么比软件 walk 快一个数量级。
ARMv8-A 翻译体制与 x86 差异很大:两套 TTBR、可选 4K/16K/64K granule、ASID 原生标签、nG/G 分离。本文梳理 VMSAv8-64 核心:TTBR0/1、granule、descriptor、ASID、VHE、MTE、BTI。
TLB 容量有限,shootdown 在多核下常是扩展性终点。本文讲 TLB 层级、PCID/ASID 命中、shootdown 代价、INVLPGB 与 arm64 TLBI 广播、lazy tlb、huge page 对 TLB 的放大效应。
进程地址空间在内核里靠 mm_struct + VMA 链表/树描述。本文讲 mm_struct 核心字段、VMA 从红黑树到 maple tree 的改造、anon_vma 反向映射、mmap_lock 争抢。
缺页(page fault)是 VM 的核心事件——PTE 不 present 就触发 #PF。本文讲 major/minor/COW/swap/userfault 五种缺页控制流、do_page_fault 调用链、hugefault、userfaultfd 在 CRIU/Live Migration 的角色。
页缓存是 Linux I/O 的灵魂缓冲层。本文从 VM 视角讲 address_space、radix 到 XArray 改造、folio 抽象、readahead 策略、writeback 与 dirty throttling、memcg 对页缓存的约束。
内存真的耗尽时,内核的最后手段是 OOM Killer——选一个进程杀掉。本文讲 oom_score 算法、oom_score_adj 调优、memcg OOM、PSI 驱动的 systemd-oomd/earlyoom,以及如何追查 OOM 事故。
多路服务器里内存不再平等——本地访问和远程访问延迟差 2-3 倍。本文讲 NUMA 拓扑、mempolicy、AutoNUMA、NUMA balancing、CXL 带来的分级内存层次,以及 NUMA 感知的生产调优。
大页能让一条 TLB 覆盖 2MB 乃至 1GB,但 THP 为什么在数据库里默认关掉?本文讲 HugeTLB 预留池、THP 的 khugepaged、defrag stall、madvise 模式、file-backed THP、以及工程上的取舍。
调度是在有限 CPU 上分配无限需求的艺术。本文从 FCFS/SJF/RR/MLFQ/Fair-share/Lottery/Stride 一路讲到 EDF/CBS,梳理响应-吞吐-公平三难;给出 Mutexpriority inversion、Multi-level feedback、starvation 的定义,以及为什么任何调度目标都不能同时最优。
CFS(Completely Fair Scheduler)从 2.6.23 统治 Linux 18 年。本文讲它的核心数据结构:sched_entity、cfs_rq、按 vruntime 排序的红黑树;vruntime 随 nice 加权的公式;sched_latency_ns/min_granularity 如何决定周期;wake-up preemption、autogroup、group scheduling 的来龙去脉。
Linux 6.6(2023 年 10 月)把默认调度器换成了 EEVDF(Earliest Eligible Virtual Deadline First)。本文讲 EEVDF 的两个新概念——eligible time 与 virtual deadline——如何把「公平」与「延迟」统一,latency-nice 给交互式任务的意义,以及早期 benchmark 与 PREEMPT_RT 的关系。
Linux 里的实时:SCHED_FIFO/RR 提供优先级调度,但原版内核仍有不可抢占点。PREEMPT_RT 补丁集 20 年后(6.12)合入主线,把几乎所有 spinlock 变 rt_mutex、IRQ 变线程。本文讲 RT 调度语义、RT-throttling、cyclictest 基线、优先级继承、以及 RT 部署的陷阱。
SCHED_DEADLINE 是 Linux 3.14 合入的 EDF+CBS 调度类。本文讲 (runtime, deadline, period) 三元组、全局 EDF 与准入控制、CBS 带宽服务器、用 sched_setattr 部署 DEADLINE 任务、为什么 DL 与 cpuset/cgroup 互斥,以及视频、机器人、无人机场景。
Linux 是「每 CPU 一个 runqueue + 周期性 migration」。本文讲 sched_domain 层级 (SMT/MC/DIE/NUMA)、wake-affine、idle pull/periodic push、imbalance 判定;NUMA Balancing 在多 socket 上的作用、prefer_sibling、energy-aware 新维度;经典负载均衡 bug 与诊断。
ARM big.LITTLE(2011)和 Intel Alder Lake(2021)之后的 P-core + E-core 让「CPU 不再等价」。调度器必须知道「这任务放大核值不值」。本文讲 CPU capacity、util_avg、PELT、misfit migration、EAS 能量模型、UCLAMP 用户态提示、Intel Thread Director。
用户抱怨「慢」时第一问题:是 CPU 本身跑得慢,还是调度器让你等?本文讲 runq latency、wakeup latency、block time 三线拆分;perf sched、bpftrace runqlat、schedviz 工具链;生产案例:CFS quota throttle、NUMA 迁移、PSI 告警。
CPU 没事干时也要管——进 C-state 太浅省不到电、太深退出延迟大。本文讲 cpuidle 架构、menu / teo / haltpoll governor、C-states 能耗-延迟权衡、PC6/PC10 的 uncore 停摆、idle_inject 与 cluster idle、诊断与调优。
CPU 频率不是一成不变——按负载动态拉升拉低是功耗最核心的杠杆。本文讲 cpufreq 架构、历史 governor(performance/powersave/userspace/ondemand/conservative)、为什么 schedutil 取代 ondemand、Intel HWP 与 amd_pstate 的硬件托管路径、per-task UCLAMP 对频率的影响。
从裸机监控器到微内核再到 unikernel 与 serverless,OS 这个抽象层在六十年里被反复挑战又反复回归。本文不做教科书式定义,而是回到工程视角,提炼 OS 真正在做的五件事:资源抽象、复用、隔离、公平、可观测性。以此为尺,丈量宏内核、微内核、VMM、unikernel、serverless 各自的胜负边界。
要理解 Linux 的很多古怪决定,得回到 Multics、Unix V6/V7、BSD 的历史语境。本文沿时间线梳理 Unix 家谱,挑出每一代留下的设计遗产——fork/exec、一切皆文件、管道、可重定向的 stdin/stdout、9P、命名空间——并指出哪些被 Linux 发扬,哪些被抛弃,哪些仍在 Plan 9 的血脉里孤独活着。
微内核是理论正义但工程失败?Linux 宏内核赢了只是因为先上车?三十年前的那场论战,在 seL4 形式化正确、L4 家族把 IPC 做到单 syscall、Fuchsia 真正商用的 2020s,我们应该怎么重新看?本文用四个可量化的维度——性能、可维护性、隔离性、可验证性——把四种内核架构(宏、微、混合、Exokernel/Unikernel)摆到同一张尺子上对齐。
OS 的隔离能力在哪里落地?CPU 提供了特权级、MMU、MPU、enclave、VMX 等一串原语,OS 把它们组合成进程/用户/内核/hypervisor 等隔离层级。本文从 x86 ring 0-3、SMM、ARMv8 EL0-3 起步,梳理 SMEP/SMAP/PAN、KPTI、CET、MTE、PKU、IBRS 等缓解机制,说清楚每一项挡的是哪一类攻击。
系统调用是 OS 最稳定的接口。本文拆解 Linux syscall 的参数寄存器约定、返回值规范(负 errno 与 2-value ABI)、x86_64 SYSCALL、arm64 SVC、RISC-V ECALL、Windows NT 的 int 2e/syscall/SYSENTER 历史;说明为什么 Linux 承诺 \"don't break userspace\"、什么东西算 syscall ABI、vDSO 如何用共享内存加速、Go/musl/glibc 各自怎么实现 syscall stub。
内核代码不能像用户代码那样自由访问任何指针。本文围绕 Linux 的 access_ok / copy_from_user / get_user_pages / pin_user_pages / __user 注解,说明用户页在内核视角的生命周期;再把视角扩展到 capability、namespace、seccomp、Landlock、LSM 等软件边界机制,汇成一张内核对用户态信任的全景图。
POSIX 标准定义了 \"一个像 Unix 的 OS 应该长什么样\",但没有哪个真实 OS 完全等于它。本文对照 POSIX 基准,列出 Linux、FreeBSD、macOS、Windows 的扩展与偏离:Linux-only 的接口(epoll、io_uring、eventfd、prctl)、BSD-only(kqueue、pf)、NT 的异步模型、符号链接/路径语义差异、signal 语义的方言、fork 的地位演变。
\"微内核更安全\"、\"零拷贝零开销\"、\"实时 OS 等于高性能\"、\"Docker 很轻因为没有 OS\"……工程界流传许多关于 OS 的简化叙事,其中不少在深入语境下是错的。本文把十二条典型错觉逐一拆开看。
fork 在 1971 年的 PDP-7 上是一句几十行的汇编;五十年后在一台 256GB 内存的服务器上同一句 fork() 要复制几百万个页表条目。本文讲 fork 的语义、COW 的账本、vfork/clone3/posix_spawn 的替代谱系,以及 fork 与多线程、大内存、JIT、容器相性差在哪里。
同样一个 'concurrent' 的需求,OS 级 1:1 线程、用户态 N:1 协程、调度器混合 M:N、运行时虚拟线程各给出了不同答案。本文梳理 LinuxThreads → NPTL 的演进、Solaris LWP 的失败、Go GPM / Java Loom / Erlang BEAM / async-await 的选择,以及 M:N 模型的阿克琉斯之踵:阻塞 syscall。
Linux 里「一个进程/线程」对应的内核数据结构是 struct task_struct,8KB 左右,几百个字段。本文把它切成 PID/凭据/内存/文件/信号/调度/namespace/追踪 八个区域,讲清楚 current 宏、thread_info、per_task 栈与 task_struct 的布局关系,以及字段变化背后的十年演进。
一个进程从诞生到尸体被回收,在内核里走过六个阶段:clone → run → exec(可选)→ exit → zombie → release。本文按阶段讲 do_fork、bprm_execve、do_exit、release_task,以及 waitpid/pidfd/subreaper 的收尸规则、孤儿与僵尸的语义、systemd PID 1 的特殊性。
signal 在 Unix 里几乎等同「异步打断」,但它的 API 踩满雷:不可重入的 handler、ASS-safe 函数清单、SIGCHLD 丢失、多线程语义、SIG_DFL 的历史包袱。本文讲 kill/tgkill/rt_sigaction、signalfd、pidfd_send_signal、async-signal-safe 的真实边界,以及为什么新代码应该尽量把 signal 转成 fd。
管道是 Unix 最古老的 IPC。但内核里它不是一条 FIFO 字节流——它是一个环形页缓冲(pipe_buffer 数组),支持 splice/vmsplice 零拷贝。本文讲 pipe/pipe2、PIPE_BUF 原子写边界、O_NONBLOCK 与 SIGPIPE、命名管道 FIFO、socketpair 与 SCM_RIGHTS 传 fd、splice/tee 的数据平面优化。
共享内存是最快的 IPC,但 API 分裂成三代:SysV shmget/shmat、POSIX shm_open、现代 memfd_create。本文讲三者的内核差别、hugetlbfs 的大页共享、memfd sealing 在 GPU/Wayland 里的安全作用、以及 /dev/shm 的 tmpfs 真相。
消息队列承诺「有边界的带优先级的 IPC」,但 Linux 上两代 API(SysV msg、POSIX mq)都很冷清。内核内的 kdbus 曾想成为下一代系统总线,最终被拒。本文讲三者的设计、使用限制、以及为什么现代系统几乎都改走 Unix socket + 序列化库 + userspace broker。
namespace 把全局内核资源(pid、mount、net、uts、ipc、user、cgroup、time)切成多个互不可见的视图。本文讲 7 种 namespace 的语义、unshare/setns/clone3 API、user ns 的 uid 映射、rootless 容器、namespace 与 cgroup 的分工、以及 pid ns init 的特殊待遇。
cgroup v2 把 v1 的多 hierarchy 统一成单一树。本文讲 unified hierarchy、controller 清单、cpu.weight/io.weight/memory.max、PSI 压力指标、systemd slice/scope/service 层级、cgroup delegation 与 rootless、以及 cgroup v2 的诊断姿势。
110 篇长文,从操作系统的基础抽象到调度、虚拟内存、文件系统、并发、安全、前沿方向。以 Linux 6.x 主线为实现参照,辅以 FreeBSD、XNU、Windows NT、实时 OS 的对照。