agentleFS
TbusOSTbusOS/sky-skills/skills/kernel-explain/SKILL.md

kernel-explain

Skill3 starsChanged 32 days agoMITView on GitHub

讲 Linux 内核原理的思路:内容按什么顺序、分几层讲,每层的材料去代码哪里取。本 skill 只放思路,不放技术事实 —— 事实每次从 user 指定的那棵内核树现查。动笔前先定读者目的(面试复习只讲核心技术的来龙去脉)、定树、定版本、定架构,再列小白的疑问链并按依赖排序,然后七层:① 一句话说这块在解决什么矛盾 ② 全貌图:硬件自己做什么、内核代码做什么、两边靠什么衔接(软件写好让硬件读的表和寄存器 / 硬件做不下去时进内核的异常入口),后文每个名词都要在图上有位置 ③ 主路径:从入口顺着最常走的分支读到底,一个具体例子贯穿 ④ 岔路:主路径第几步、什么条件、去哪(show_guard_chain.py 列条件)⑤ 演变线:从「什么都没有」讲起(如没有 MMU 的单片机),每个技术点按六格讲:没有它时 / 会怎样(带数字)/ 所以有了它 / 它怎么做 / 边界(上限多少、谁定的,芯片数字查 TRM)/ 代价(引出下一个点);讲通用原理时用读者的架构举例再给各架构对照表;设计意图从提交说明取(why_this_code.sh),取不到标 [推断] ⑥ 细节下沉:file:line、版本平台差异放最后 ⑦ 口述版:30 秒 / 2 分钟 / 追问。聊天里接追问时,第一句先说它在全貌图哪个位置。配 check_explain.py(E1–E9,md 和 html 都能查,带反向自测)。部件第一次出场时带一句「没有它会怎样」。TRIGGER: 讲内核原理 / 讲清楚 X 的原理 / 内核面试复习 / 整体框架 / 来龙去脉 / 讲本质 / 从设计角度讲 / 为什么这么设计 / 怎么演变来的 / 小白能懂 / 高维度讲 / 讲义太细记不住 / 这块的全貌 / 硬件流程和软件流程. DO NOT TRIGGER: 写或改内核代码(linux-kernel-dev)、讲一个代码改动(change-impact-brief)、只问用哪种形式讲(explain-ladder)、做页面的配色版式(anthropic-design 等)。

The file

Files
SKILL.md

讲内核原理:先全貌,后细节

2026-10-20 user 看完一份按问答整理的内存讲义后说: 「很精准没问题,但不适合复习面试使用,因为太多的细节,记不住」 「我们要用更高维度的角度去表达清楚这些问题的本质是什么,而不是一股脑钻入细节里面去, 所以讲一个问题要把整体框架讲清楚来龙去脉」 「不可能代码一开始编写就面面都能考虑完全,linux 内核也是长期发展下来才慢慢变出这么多设计」

0. 这个 skill 管什么

管不管
讲的顺序、分几层、每层讲到什么程度技术事实本身。事实每次从 user 指定的那棵树现查,不从本 skill 抄,也不凭记忆
每层的材料去代码哪里取、用什么命令取用文字、图还是网页讲,句子怎么写:归 explain-ladder
写完后的结构检查页面配色版式:归 anthropic-design 等

为什么事实不放进来:同一个问题,板子上的 4.14 ARM32 和上游 6.x arm64 答案常常不一样。 放进 skill 的事实会过期。它还会被当成查过的结论直接用。本页出现的技术词只是为了说明写法。

1. 三种讲坏的方式

每一种单看都不算错,讲出来的事实也可能全对。

讲法长什么样读者的结果
按提问顺序排把问答记录整理成文档:第 1 轮、第 2 轮……每段都对,合起来没有一张图,记不住
按代码或教材顺序排一个函数一个函数、一个模块一个模块讲,满篇 file:line适合查,不适合理解:不知道为什么要有这么多种
只追最新一问每次只答眼前这一问,答得很深要追问很多轮才拼出全貌。2026-10-18/19 一份 AI 问答记录,user 追问了 34 轮

共同的病:没有先给全貌。读者手里没有图,每个新知识点就没处挂。

2. 开工前:定读者目的、定树、定版本、定架构

先问这份东西给谁、拿去干什么,它决定讲多深。user 2026-10-20:「这个 html 是面试用我来复习的用的, 这个大前提不要忘记了,把内存管理主要的核心技术来龙去脉说清楚就好了」。

目的讲到哪不讲
面试复习核心技术的来龙去脉;每个点的边界只留会被问到的一两条;出处折叠起来旁支(别的架构的细节、很新的特性),除非被问到
实战排查主路径和岔路要细到函数和条件;出处展开演变线可以短
给新人讲一句话、全貌图、主路径、演变线细节和出处只给入口
T=<内核树>                      # user 指定的那棵;板子的问题用板子的树
git -C $T describe --tags       # 版本
grep -E '^CONFIG_(ARM64|ARM|X86)=' <板子的 .config>   # 架构;没有 .config 就问
  • 讲面试通用原理时,默认用上游较新的稳定版;讲 user 板子上的行为时,用板子那棵树。两者不一样时,⑥ 里列差异表。
  • 换了树,前面查的 file:line 全部作废,重查。

3. 七层

层讲什么讲到了的标准材料去哪取
⓪ 疑问链没学过的人会依次问的问题,按依赖排序每个问题都能落到下面某一层user 的原话;再补上它们依赖的前置问题
① 一句话这块在解决什么矛盾:「要 X,但 Y,所以 Z」是矛盾,不是定义对外接口承诺了什么 + 硬件给了什么限制
② 全貌图硬件做什么 / 软件做什么 / 两边怎么衔接后文每个名词都能在图上指出位置写寄存器的地方、硬件读的表、异常和中断入口
③ 主路径最常走的那条,从入口走到底,步骤编号一个具体例子贯穿;不岔开从入口函数顺着读;板上用 ftrace 抓一次真实路径
④ 岔路第几步、什么条件、去哪、正常还是 bug「哪里会 / 不会 X」都在这层用表答主路径函数里的 if / switch / 出错 goto
⑤ 演变线从「什么都没有」讲起;每个技术点:没有它时 → 会怎样 → 所以有了它 → 它怎么做 → 边界 → 代价六格齐,会怎样带数字引入它的提交说明、Documentation/、芯片手册(边界)
⑥ 细节数字、字段、file:line、版本平台差异主线里没有,都集中在最后当次查的那棵树
⑦ 口述版30 秒、2 分钟、追问预测能直接念出来前六层

①② 给读者一张图,③④ 让他在图上走一遍,⑤ 告诉他图为什么长这样,⑥ 给要查证的人,⑦ 给要讲给别人听的人。

⓪ 疑问链:按依赖排,不按代码排

先写下一个没学过的人会问什么。2026-10-20 user 给内存列的就是一条,这条的写法值得照着做:

内存怎么申请 → 怎么访问到物理内存(硬件总流程)→ 用户空间和内核空间访问有什么不同 → 页表放在哪 → 哪里有缺页、哪里没有 → VMA 是什么 → 软件流程和硬件流程各走哪些 → 线性映射、非线性映射、回收是怎么演变出来的

排序只看一条:回答 B 要用到 A,A 就排前面。

① 一句话:写矛盾,不写定义

  • 形状:「要 X,但 Y,所以 Z」。矛盾写清了,后面每个设计都能回到这句话上:它在缓解矛盾的哪一头。
  • 反例:「X 是内核中负责管理 Y 资源的子系统。」这是定义,读完不知道难在哪。<!-- ste-ok:反例 -->
  • 这句话通常没有一手出处,写的是自己的概括;Documentation/ 里有原话就引原话。

② 全貌图:硬件、软件、衔接点

内核子系统几乎都能拆成三块。这是讲内核和讲一般软件最不一样的地方:

  硬件自己做的事              衔接点                    软件(内核代码)做的事
  (不跑一行内核代码)
 ┌──────────────────┐   软件写好、硬件去读   ┌──────────────────────┐
 │ 按规则自动执行   │ ◀──── 表 / 寄存器 ──── │ 准备表、做决定、记账 │
 │                  │                        │                      │
 │                  │ ──── 异常 / 中断 ────▶ │ 处理硬件做不下去的事 │
 └──────────────────┘   硬件做不下去时叫软件 └──────────────────────┘

三块各去代码哪里找:

块找什么怎么找(按架构改 $ARCH)
软件写、硬件读写系统寄存器、写设备寄存器的地方;硬件按固定格式去读的表git -C $T grep -n 'write_sysreg|msr\s' arch/$ARCH/ 再按子系统收窄;表格式看 arch/$ARCH/include/asm/ 里带 hwdef 的头文件
硬件叫软件异常向量表 → 哪个 C 函数 → 子系统的处理函数git -C $T grep -n 'vectors' arch/$ARCH/kernel/entry*.S,从向量顺着跳转读到 C
软件这一侧有哪些块子系统目录、对外头文件、每块对外的几个函数子系统目录下的文件名,include/linux/<子系统>*.h
  • 检查标准:后文出现的每个名词,都能指出它在图上哪个框。指不出来,要么图缺了,要么这个名词不该进主线。
  • 部件第一次出场时带一句「没有它会怎样」,并指向 ⑤ 里它那一节。例:「TLB:没有它,每次访存都要先多读 4 次内存 → ⑤ A3」。 读者在 ②③ 里就知道每个部件为什么在那,不用等到 ⑤。
  • 「X 放在哪」「X 是硬件做的还是软件做的」这类问题,在这张图上应该一眼能答。

③ 主路径:一条,走到底

  • 选一个具体例子贯穿全文,后面讲岔路、讲演变都回到它。例子要小到能一步步走完:一条指令、一次系统调用、一次中断。
  • 步骤编号。每步写:谁做(硬件 / 内核 / C 库)、读什么、写什么、数据在哪。
  • 不岔开。出错、未命中、权限不对,这里都不讲,只在那一步旁边标「岔路 A」。
  • 软件流程和硬件流程分开走。混在一起讲,读者分不清哪一步是谁在做。
  • 取材:从入口(SYSCALL_DEFINE、异常处理函数、中断处理函数)顺着读,只跟最常走的分支。 有板子时,用 ftrace 抓一次真实调用路径,比读代码猜的可靠:

    cd /sys/kernel/tracing 2>/dev/null || cd /sys/kernel/debug/tracing   # 老内核在 debug 下
    echo <入口函数> > set_graph_function
    echo function_graph > current_tracer; echo 1 > tracing_on
    # 触发一次,然后
    echo 0 > tracing_on; cat trace > /tmp/path.txt
  • 调用链要正式出图时,用 design-review/scripts/gen_call_site_figure.py 从文件按行号生成,不手抄。

④ 岔路:挂在主路径的步骤号上

主路径第几步条件走去哪结果(正常还是 bug)
  • 「哪里会 X、哪里不会」「哪里能睡、哪里不能」这类问题都在这层答,用表。
  • 取材:主路径上每个函数里的 if / switch / 出错 goto。某一行在什么条件下才执行,用 linux-kernel-dev/scripts/show_guard_chain.py <file>:<line> 列出外层所有条件,不要只看 grep 到的那一行。

⑤ 演变线:每个技术点都先问「没有它会怎样」

2026-10-20 user:「内存移动,内存回收,这些一开始是不会有的设计,是了解了本质后,慢慢遇到问题想出来的设计, 如果没有,会怎样,所以才慢慢有了这些设计」「没有 mmu 一样可以申请内存的,但是会面临什么问题,有些场景是没有 mmu 的例如单片机……tlb 也是同样的思路解释,没有 tlb 怎样,所以后面才诞生了 tlb」

起点是「什么都没有」,不是「已经有了一半」的系统。讲内存就从没有 MMU 的单片机讲起:它照样能申请内存, 问题出在别处。每一个技术点都是前一步撞上问题才加的,所以每个点都按这六格讲:

格写什么例:TLB
没有它时之前的做法,它照样能工作每次访存都走 4 级页表
会怎样具体场景、带数字,坏在哪每次访存前先多读 4 次内存
所以有了它一句话:加了什么MMU 里放一小块缓存记最近的翻译
它怎么做两三句机制,够复述就停先查缓存,没命中才走表,走完硬件填进去
边界能力范围、上限、谁定的项数由芯片定;能覆盖多大内存
代价它带来的新问题,引出下一个点缓存会过期,改了页表要作废
 没有它时 ──撞上──▶ 会怎样(带数字) ──于是──▶ 有了它 ──代价──▶ 下一个点 ──▶ …
  • 六格必须齐。写不出代价,说明没想清楚,没有免费的设计。
  • 问题要带数字或具体场景,数字从树里的常量算(页大小、级数、默认参数),算式写出来。
  • 线可以有两条,对着全貌图的两半:硬件那一半怎么变的、软件那一半怎么变的。
  • 这是逻辑上的演变,不是编年史。
  • 引擎是「按你的想法做会怎样」。读者提一个更简单的方案,就按他的方案推下去,推到坏为止。 坏在哪一步,就是现有设计存在的理由。先承认他的想法里对的部分。
  • 分清两种「为什么」:为什么需要(不这样就坏)和为什么选这个(还有别的路,为什么没走)。
  • 「没有它时」最好有真实的样本:内核常常自己就留着没有它的那个版本,比如 CONFIG_MMU=n 的无 MMU 模式和它的文档。 拿它当证据,比自己设想「没有它会怎样」可信。
  • 边界写三件事:能力范围和上限是多少、由谁定(架构 / 具体芯片 / 内核配置 / 运行时)、去哪查。
    • 架构和内核配置的上限:Kconfig、页表格式的头文件、内核开机读的 ID 寄存器。
    • 芯片定的数(TLB 项数、物理地址位数、ASID 位数):去查这颗芯片的技术参考手册(TRM),内核源码里没有。 user 的板子是哪颗核,就查哪颗核的 TRM;手册存一份到本地,出处写文档号和章节。
    • 能在板上读的就读(/proc/cpuinfo、ID 寄存器、/sys),读到的比手册更贴近这块板。
    • 读者问「能不能随便扩」「是不是 128 位」这类问题时,答案就在边界这一格:谁定的、为什么不能随便改。
    • 边界写几条看读者目的(§2):面试复习只留会被问到的一两条。
  • 讲通用原理,用读者自己的架构举例,再给一张各架构对照表。 user 2026-10-20:「我这边主要是 arm32,arm64 的架构的, 哪怕以后是 x86 或者 riscv 等,这些通用原理都是一样的」。原理用一套话讲;对照表只列「同一件事在各架构叫什么」 (寄存器名、入口函数名),并写出它们在哪里汇合到同一段通用代码。对照表里每一格都要在树上核过。
  • 取材:设计意图的一手记录是引入它的提交说明。

    linux-kernel-dev/scripts/why_this_code.sh <file> [符号]    # 谁、哪笔提交、提交说明怎么写的
    git -C $T log -S'<符号>' --reverse --oneline | head -3      # 符号最早什么时候出现

    还可以看 Documentation/ 和 lore.kernel.org 上的讨论。取不到一手记录的设计意图,标 [推断]。

⑥ 细节下沉

  • 数字、结构体字段、file:line、「这个版本这样、那个版本那样」都放最后的「细节和出处」一节。主线里最多留一两处会改变判断的。
  • 下沉不等于不核。每个事实照样要有出处,只是放在后面。
  • 版本、平台差异汇总成一张表:git -C $T show <tag>:<file> 对照着查,不散在正文里。
  • 「某处没有 X」这种结论,写上搜索条件和范围,再用同一条件在一个确定有的地方搜一次,证明条件本身有效。

⑦ 口述版

  • 30 秒:一句话 + 全貌图的三块。
  • 2 分钟:主路径 + 一条演变线。
  • 追问预测:每条一句答案,并注明展开时去第几层。

4. 写每一段时

做说明
每节第一句就是答案不写「下面我们来看……」这类预告
从读者的直觉出发先说直觉里对的部分,再指出它在哪一步不成立,用一个具体场景演出来
一个例子贯穿同一个例子从头用到尾,不每节换一个
对比用表A 和 B 的区别,按维度列成表
比喻最多一个,说清在哪失效比喻帮读者记住结构,失效处防止他推错
不确定就标出来设计意图写 [推断];没查的写「没查」

不做的:

不做为什么
夸读者(「直觉非常敏锐」「神来之笔」)占篇幅,不带信息
夸张修辞(「灭顶之灾」「死个痛快」)读者分不清哪句是事实、哪句是修辞
讲得顺就当讲对了讲得越顺,错处越难发现,见 references/lessons-from-qa.md
每次回答末尾都问「要不要再聊 X」追问集中放在口述版里

5. 和「技术解释五问」的关系

五问(是什么 / 没有它会怎样 / 为什么这么设计 / 什么场景用 / 机制)管一个名词,七层管一整块。 名词在七层里出场时,五问分到各层去答:

五问在哪层答
是什么② 全貌图上它那个框;第一次出场时带一句「没有它会怎样」
没有它会怎样⑤ 它那一节的「没有它时 / 会怎样」
为什么这么设计⑤ 它那一节的「所以有了它 / 代价」
什么场景用③④ 主路径或岔路的第几步
机制⑤ 的「它怎么做」只讲到能复述;再细的放 ⑥

五问之外,⑤ 每一节还多一格「边界」。

6. 三种场合

场合做什么
写讲义或讲解页定树 → 七层写满(大纲可从 references/outline-template.md 起步)→ 跑 §7 的检查。网页走 anthropic-design,图宽和句子走 explain-ladder
聊天里接一个追问第一句先定位:「这是全貌图里 X 那块,主路径第 N 步的岔路」,再答。还没给过全貌图,先画一张 ≤ 80 列的 ASCII 小图。一次只答这一问,但要让它挂在图上
改写旧资料把问答记录或细节讲义拆成名词清单 → 每个名词放进七层 → 原文的 file:line 全部挪到 ⑥,并在当次的树上重核一遍

7. 检查

K=~/.claude/skills/kernel-explain/scripts
python3 $K/check_explain.py <讲义.md 或 .html>
printf '%s' "<草稿>" | python3 $K/check_explain.py --stdin
python3 $K/check_explain.py --strict <文件>      # WARN 也算失败
python3 $K/check_explain.py --self-test          # 19 条,15 条是故意写坏的
编号查什么级别
E1有全貌图、主路径、演变线三节(只认小标题)FAIL
E2有一句话、岔路、细节、口述版四节WARN
E3全貌图在主路径前,主路径在演变线前WARN
E4有图,且第一张图出现在第一个 file:line 和第一段代码之前FAIL
E5细节一节之外,file:line 不超过 3 处WARN
E6演变线里「没有它」「代价」各至少 2 次,「边界」至少 1 次WARN
E7演变线里有 [推断] 或提交号WARN
E8没有夸读者、夸张修辞的词FAIL
E9七层小标题下的第一句不是预告WARN

退出码 0 过 · 1 有 FAIL(--strict 时 WARN 也算)· 2 用法错。 故意放的反例:Markdown 那一行写 explain-ok,HTML 元素加 data-explain-ok,E8、E9 跳过它。

检查只看结构:有没有、顺序对不对、主线里出处多不多。讲得对不对,靠当次在树上核。 讲没讲清,靠读者测试:新开一个 agent,只给它这份讲义,让它回答 ⓪ 那条疑问链。它答不出、答错的地方,就是没讲清的地方。

8. 文件

文件作用
scripts/check_explain.pyE1–E9;md 和 html 都能查;--self-test 带「故意写坏,必须报」的用例
references/outline-template.md七层大纲空模板,只有结构
references/lessons-from-qa.md从一份 102 页 AI 问答记录里学到的讲法:哪些拿来用,哪些不学

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.