正常
导引:静态审计瞎的那根轴
这一章换一条线,不讲新功能,讲怎么验证。起因是一次审计:静态债务表量的是「代码写得对不对」,但真正难调的 bug,问的全是另一根轴上的事——「这段代码有没有真被跑到」「这个机制有没有真生效」「崩了能不能一眼看懂」。静态审计对这根轴是天生的瞎子。最难调的 bug,根因排前几位的全是动态性的:机制没真生效、并发没被压到、测试基建跟生产不一样。这一章把验证基建补上,核心是两件事:一是戳穿一个名存实亡的 SMP 测试(
run-kernel-test-smp带着-smp 2,但测试内核从不唤醒第二个核,套件从头到尾只跑了 BSP),二是给故障加一个崩了也能看见的窗口(第一个 fault 的现场,在递归崩掉之前 dump 到一个永远活着的通道)。验证靠测试基建自己——SMP 那条腿真的 boot 了 AP、读了回 CPU 配置;故障 dump 真的能在嵌套崩之前留住首故障。一条诚实的边界先说在前头:这是验证/调试基建,不是用户能用到的新能力。它的产出是「CI 能抓到以前抓不到的 SMP/并发 bug」「崩了一行定位」,不是「OS 多了一项功能」。
这章咱们要点亮什么
- 静态审计 vs 动态验证:静态量「写得对不对」,动态问「跑没跑到、生没生效、崩了看不看得见」——两根轴,静态表对动态性瞎。
- SMP 空转盲区:
run-kernel-test-smp带-smp 2但不唤醒 AP,等于只跑了一个核——所有 SMP-only bug 它都抓不到。 - gated 钩子范式:给生产 SMP 代码插一个测试钩子,但
fn=null时生产字节完全不变——既能让测试驱动 AP,又不污染生产路径。 - 首故障捕获:崩了之后,第一个 fault 的现场要在任何可能递归进第二个 fault 的代码之前,dump 到一个永远活着的通道(debug console)。
静态审计瞎的那根轴
先说为什么要专门拿一章讲「验证」。之前做过一轮静态债务审计(代码质量那类),量出来一堆「这里没检查返回值」「那里锁序不对」之类的静态问题。但真正让人调试到半夜的 bug,根因几乎都不在静态表上:
- 一个机制写了但根本没生效(比如某个保护位设了代码、但运行时从没走到设它的路径);
- 一段并发代码从来没被真正压到过(两个核从没在同一刻撞上那条临界区);
- 测试基建跟生产不是一回事(测试里走 A 路径,生产走 B 路径,测了等于没测);
- 崩了之后现场被覆盖(第一个 fault 还没看清楚,递归的第二个 fault 就把日志冲了)。
这些是动态/环境性的另一根轴,静态债务表天生看不见。真要查根因,这几类往往排在最前:机制没真生效、并发没压到、测试基建跟生产对不上。所以这一章专攻验证基建,目标是「把以前要靠多个人、多个会话 forensics 才发现的 bug,变成一次 CI 红灯」。