知识全景图/ 软件工程与系统/ 计算机系统底座/ 操作系统内核机制底座

操作系统内核机制底座

调度、虚拟内存、文件系统、IO 多路复用、网络栈、cgroup 与 namespace 的工程解释

阅读边界: 这页不写内核源码逐行分析,而是解释应用在 Linux 上运行时,内核如何调度 CPU、管理内存、抽象文件、处理网络和限制容器资源。

本页主责: 只负责“应用与 Linux 内核资源之间的边界”:调度、虚拟内存、VFS、网络栈、cgroup、namespace。CPU 微架构、语言 GC/JIT、SSD 介质和 GPU 数据搬运只做跳转,不在本页展开。

前置设计训练: 如果你想先从“为什么需要进程、内存隔离、系统调用、文件系统和驱动”开始,而不是直接进入 Linux 机制,可以先看 如何设计操作系统

一句话判断: 线上很多“应用问题”,其实是应用、运行时、内核和资源限制共同形成的系统问题。
一、内核负责的五类事
调度
决定哪个线程在什么时候获得 CPU,以及等待、唤醒、抢占和优先级如何影响延迟。
内存
通过虚拟内存、页表、缺页异常、页缓存和回收策略管理进程地址空间。
文件与设备
用 VFS、文件描述符、块设备和驱动把磁盘、Socket、Pipe 等统一成可操作对象。
网络
处理 TCP/IP 协议栈、连接状态、缓冲区、拥塞、重传、软中断和路由。
隔离与限制
namespace 提供视图隔离,cgroup 提供 CPU、内存、IO 等资源限制。
二、进程、线程与调度
机制关键问题生产信号
上下文切换CPU 从一个线程切到另一个线程,需要保存和恢复执行现场线程过多、锁等待、阻塞 IO 会让上下文切换飙升
Run Queue等待 CPU 的可运行线程队列队列长说明 CPU 竞争明显,但也要结合核心数和负载类型看
阻塞 / 唤醒线程等待 IO、锁、条件变量或定时器后被唤醒CPU 不高但延迟高,常常是大量线程在等待资源
CPU Throttling容器 CPU quota 用完后被限制运行容器里 CPU 看似没满,但延迟周期性抖动
三、虚拟内存、页缓存与 OOM
机制解决什么误判风险
虚拟地址空间让每个进程看到独立连续地址空间地址空间大不等于物理内存够,RSS 才更接近实际占用
缺页异常访问尚未映射或未载入内存的页时进入内核处理冷启动、mmap、大文件扫描可能因缺页带来延迟抖动
Page Cache把文件内容缓存在内存中,提升读写性能内存被 cache 占用不一定是泄漏,关键看可回收性
内存回收在压力下回收页缓存、匿名页或触发 swap / OOM容器 limit 下,宿主机有内存也可能 OOMKilled
四、VFS、文件描述符与 IO
对象工程意义常见事故
文件描述符文件、Socket、Pipe、eventfd 等都通过 fd 被应用持有fd 泄漏导致无法接新连接或打开文件
VFS统一不同文件系统接口删除文件但进程仍持有 fd,空间不会释放
fsync要求数据真正落盘高频同步写会造成尾延迟和 IO wait
mmap把文件映射到进程地址空间缺页、脏页写回和文件生命周期会影响稳定性
五、epoll、io_uring 与网络栈
机制适合什么排查关注
epoll大量连接的事件通知模型,常见于网关、Nginx、Netty、Node.js事件循环是否被阻塞、连接是否积压、回调处理是否过慢
io_uring更低系统调用开销的异步 IO 接口收益取决于内核版本、驱动支持和应用模型
TCP 栈连接、重传、拥塞、缓冲区、TIME_WAIT、keepalive偶发超时要拆 DNS、建连、TLS、发送、下游处理和回包
软中断内核处理网络包等事件的一部分包量高时可能单核软中断打满,应用层看不出明显热点
六、容器隔离:namespace 与 cgroup
机制它隔离 / 限制什么生产问题
PID Namespace进程视图容器里看到的 PID 和宿主机不同,排查要对应映射
Network Namespace网卡、路由、端口和网络栈视图本地通、容器不通,可能是路由、DNS、iptables 或 CNI 问题
Mount Namespace文件系统挂载视图配置文件、证书、日志路径和权限在容器里可能不同
cgroupCPU、内存、IO、进程数等资源限制OOMKilled、CPU throttling、IO 限速都来自这里
七、为什么应用问题会变成内核问题
应用现象内核机制为什么会发生证据
CPU 不高但接口慢调度、阻塞、唤醒、IO 等待线程可能都在等锁、磁盘、网络、连接池或 cgroup quota,而不是在 CPU 上运行线程栈、run queue、上下文切换、iowait、Trace span
内存看起来满了Page Cache、匿名页、RSS、内存回收Linux 会积极使用空闲内存做缓存,满不等于泄漏;容器 limit 又会改变判断边界RSS、cache、available、cgroup memory、OOM 日志
磁盘满但删文件没用VFS、inode、打开文件描述符文件被删除后,如果进程仍持有 fd,空间仍然被占用lsof deleted、df / du 差异、进程 fd
网络偶发超时TCP 状态、重传、队列、软中断、路由网络不是一条线,DNS、建连、TLS、发送队列、接收队列、下游处理都可能排队重传率、连接状态、网卡队列、软中断、Trace
容器里慢,本机不慢cgroup、namespace、CNI、挂载和安全上下文容器看到的是被限制和隔离后的资源视图,不等于宿主机真实全局视图cpu.stat、memory.events、mount、resolv.conf、iptables / CNI
八、内核机制到排障路径
先看什么如果异常下一步常见误动作
CPU 用户态 / 系统态系统态高查系统调用、网络包、文件 IO、锁和内核路径只优化业务函数
上下文切换切换过高查线程数量、锁等待、阻塞 IO、线程池和调度继续加线程
iowait / 队列深度IO 等待高查日志、数据库、fsync、小文件、远程存储和 page writeback只怪数据库 SQL
fd / socketfd 接近上限查连接泄漏、文件泄漏、TIME_WAIT、连接池释放只调大 ulimit
cgroup 事件出现 throttled / oom / io pressure查容器 limit、请求量、运行时参数和节点资源竞争只看宿主机 top
九、真实场景诊断卡
场景错误猜测真实机制证据动作
容器 CPU 看起来不高,但接口周期性变慢应用代码偶发慢cgroup CPU quota 用完后被 throttling,线程虽然可运行但拿不到 CPUcpu.stat 里的 throttled_time / nr_throttled、P99 周期性尖刺、宿主机负载调整 request / limit,减少同节点混部,优化 CPU 热点,避免用平均 CPU 掩盖 throttling
删除大日志后磁盘空间没有释放df 命令坏了或文件系统异常进程仍持有已删除文件的 fd,VFS 只有最后引用释放后才回收空间df 与 du 不一致,lsof 看到 deleted 文件,进程 fd 指向已删除路径让进程重开日志、重启持有进程或触发日志框架 reopen,不要继续盲删目录
服务连接数很多,重启后短时间又耗尽ulimit 太小连接泄漏、TIME_WAIT、半开连接、下游慢或连接池归还异常ss 连接状态、fd 数、连接池 active / idle、下游耗时和超时配置先分类连接状态,再修复释放路径、超时、keepalive 和池化策略
内存满但看不到明显堆泄漏监控不准RSS 可能来自堆外内存、线程栈、mmap、page cache 或 native 库heap 与 RSS 差距、pmap、smaps、direct memory、线程数、cgroup memory.events分层拆 heap / non-heap / native / cache / cgroup,不要只调 JVM heap
十、典型误判
误判为什么错更好的说法
top 里 CPU 不高,所以系统没压力线程可能在 IO、锁、quota、连接池或下游排队,不在 CPU 上运行CPU 只是一个资源视角,还要看等待、队列和 cgroup 事件
内存满就是泄漏Linux 会用空闲内存做 page cache,容器又有自己的 limit 语义先分 RSS、heap、cache、available 和 cgroup limit
调大系统参数就算修复ulimit、连接数、队列长度只会推迟爆炸,不会消除泄漏或下游慢参数调优必须和原因修复、容量验证一起做
十一、展开案例:CPU 不高但接口慢
步骤判断关键证据
1. 先确认慢在哪里不要直接改代码,先把一次请求拆成排队、执行、下游、返回Trace span、网关耗时、应用处理耗时、下游耗时
2. 看线程是否在运行CPU 不高时,线程大概率在等待而不是计算线程栈、blocked / waiting 数、run queue、上下文切换
3. 查等待资源锁、连接池、磁盘、网络、cgroup quota 都可能让线程不在 CPU 上锁等待、连接池等待、iowait、ss、cpu.stat
4. 对齐时间线把 P99 时间点和内核 / 容器 / 下游指标对齐,避免各看各的P99 样本、容器事件、iostat、网络重传、下游 P99
5. 小步验证只改一个变量,确认瓶颈是否移动限流、缩短超时、减少并发、隔离节点、临时调大 quota 的对照结果
十二、展开案例:OOMKilled 但 heap 不高
步骤判断关键证据典型动作
1. 先确认是谁杀的应用退出、Kubernetes OOMKilled、内核 OOM killer、运行时主动退出不是一回事Pod lastState、exit code 137、dmesg、memory.events、容器重启时间线先固定事件类型,再谈泄漏或扩容
2. 拆 heap 与 RSSheap 低只能说明语言堆没满,不能说明进程内存不高JVM heap / non-heap、RSS、PSS、pmap、/proc/<pid>/smaps_rollup把内存拆成 heap、direct、metaspace、线程栈、mmap、native、page cache
3. 看容器边界容器 OOM 看的是 cgroup limit,不是宿主机整体 free 内存memory.max、memory.current、memory.peak、memory.events、Pod limit核对 request / limit,避免只看宿主机 available
4. 找增长斜率一次 OOM 只能证明撞线,连续曲线才能区分泄漏、峰值、缓存和突发流量RSS 曲线、线程数、连接数、请求体大小、DirectBuffer、mmap 文件数把内存曲线和发布、流量、批任务、GC、缓存刷新对齐
5. 分层止血先降低杀进程概率,再做根因修复;不要只无脑调大 heapOOM 前后 profile、heap dump、native memory tracking、连接池和缓存指标限制并发 / 请求体,修复堆外泄漏,调整容器 limit,给 GC 与运行时参数留安全边界
十三、展开案例:删日志后磁盘不释放
步骤判断关键证据典型动作
1. 区分 df 与 dudf 看文件系统已分配空间,du 看目录树可达文件大小;两者不一致通常是引用还没释放df -h、du -sh、挂载点、容器内外路径先确认满的是哪个挂载点,不要跨目录盲删
2. 查 deleted fd文件名被删除,只是目录项没了;进程还持有 fd 时,inode 和磁盘块仍在lsof | grep deleted、/proc/<pid>/fd、进程启动时间和日志路径找到持有者,而不是继续删除更多文件
3. 判断能否安全释放直接 kill 进程可能扩大故障;重开日志通常比重启服务更安全服务角色、是否有 reload / reopen 信号、日志框架能力、实例副本数优先 logrotate reopen、发送 USR1 / HUP、滚动重启单实例
4. 看 inode 与小文件磁盘满不只可能是字节满,也可能是 inode 耗尽df -i、目录文件数量、日志切割策略、临时文件清理策略清理小文件风暴,调整切割、保留期和目录分片
5. 固化预防磁盘事故常常不是“空间不足”,而是日志生命周期没人负责日志大小、保留天数、切割频率、采集延迟、告警阈值设置磁盘水位告警、强制日志轮转、限制单文件大小,保证删除后进程能重开文件
十四、内核排障决策树
入口症状第一层判断继续下钻核心证据容易走偏的方向
先拆 CPU 计算慢、线程等待慢、下游慢、网络慢CPU 高看 perf / 火焰图;CPU 不高看锁、IO、连接池、run queue、cgroup throttlingTrace、top、pidstat、vmstat、线程栈、cpu.stat只凭平均 CPU 判断服务没压力
OOM / 重启先确认是 cgroup OOM、内核 OOM、运行时崩溃还是健康检查杀死heap 低时继续查 RSS、direct memory、线程栈、mmap、page cache、native 库memory.events、dmesg、RSS、smaps、heap dump、NMT只调大 JVM heap,反而挤压堆外和系统余量
磁盘满先看字节满、inode 满、挂载点满还是容器层满df / du 不一致查 deleted fd;IO 慢查队列深度、fsync、远程盘、写回df、du、df -i、lsof deleted、iostat、mount跨目录盲删,或把日志删掉却不让进程重开
连接异常先分 DNS、建连、TLS、发送、下游处理、回包、连接池连接多查 fd、TIME_WAIT、CLOSE_WAIT;超时多查重传、队列、软中断、下游 P99ss、sar、网关日志、连接池指标、重传率、Trace无脑加重试,把下游和连接池压得更坏
容器异常先确认容器视图和宿主机视图是否一致资源类看 cgroup;网络类看 namespace / CNI / iptables;文件类看 mount namespacekubectl describe、cpu.stat、memory.events、nsenter、mount、resolv.conf拿宿主机 top / free 直接解释容器里的限制
十五、工具与证据表
问题优先证据常用工具 / 位置看错会怎样
CPU / 调度用户态 / 系统态、run queue、上下文切换、throttlingtop、pidstat、vmstat、/sys/fs/cgroup/*/cpu.stat把 quota 限制误判成代码偶发慢
内存RSS、heap、page cache、available、OOM 事件free、pmap、smaps、dmesg、memory.events把 page cache 当泄漏,或只看 heap 漏掉堆外
磁盘 / 文件iowait、队列深度、inode、打开 fd、deleted fileiostat、df、du、lsof、/proc/<pid>/fd删文件不释放时继续清目录
网络连接状态、重传、监听端口、队列、DNSss、ip、resolv.conf、sar、网关日志把连接池耗尽直接归因于下游不稳定
容器namespace 视图、limit、mount、CNI、资源事件kubectl describe、cgroup files、nsenter、iptables用宿主机视图解释容器里的问题
十六、训练题
题目要输出什么判分点
接口 P99 上升,CPU 只有 35%,线程数翻倍列出 5 个优先怀疑点和对应证据是否想到连接池、锁、IO、下游、cgroup,而不是只看代码
容器 OOMKilled,但 JVM heap 使用率只有 60%画出 heap / RSS / direct / thread stack / page cache / cgroup 的拆解路径是否能解释堆外和容器 limit
磁盘 df 满,du 不满给出最可能原因和验证命令是否想到 deleted file 被进程持有
偶发网络超时,只发生在高峰拆 DNS、建连、TLS、发送、下游、回包、重试七段是否避免“无脑重试”
十七、跨页读法路线
如果你现在面对先读本页哪块再跳到哪里
线上排障工具与证据表、真实场景诊断卡Linux / DevOps可观测性 / SRE
容器资源问题namespace 与 cgroup、CPU throttling、OOMKilled云原生容量治理
网络慢和连接异常epoll / TCP 栈、连接状态、软中断网络 / 流量工程
语言运行时问题调度、内存、文件描述符编译器与运行时底座
十八、互链
相关页连接关系
计算机系统底座本页是系统底座的内核机制下钻
如何设计操作系统如果要先理解 OS 抽象为什么这样设计,可以从 ToyOS 的启动、进程、内存、系统调用、文件和设备边界切入
Linux / DevOps命令和排障动作需要以内核机制为解释基础
云原生容器、Kubernetes 和资源限制建立在 namespace / cgroup 之上
网络 / 流量工程网络排障需要理解内核网络栈、连接状态和软中断