专注于 Infra 层的 AI Agent 技能平台—— 龙蜥社区 SkillHub 已收到数百个技能,当前陆续上线中。我们每周也会收到一些技能的最佳实践分享,本期给大家推荐的是 AMD 数据中心生态和应用工程部资深架构师张磊贡献的《kernel-patch-backport(内核补丁回合工具)》,核心目标是:把上游 mainline 的内核补丁安全地移植到低版本稳定内核,并证明移植后的语义与上游一致。以下是他的实战分享:
那天我删掉了 8844 行 diff
先说结论:那 8844 行,我一行都没用上。
事情是这样的。我要在一台新一代 x86 服务器(Zen5 架构,CPU family 0x1a )上验证龙蜥内核的虚拟化能力,跑的是标准的 kvm-unit-tests 。机器是刚上架的,内核是 Anolis cloud-kernel 的 5.10 分支。
命令敲下去,87 个测试项跑完,我盯着屏幕看了大概十秒钟才反应过来数字是真的:
5.10: 0 PASS / 71 FAIL (全部 timeout) / 16 SKIP复制
零通过。
同一台机器、同一个
dummy.flat
二进制,换成 Ubuntu 自带的 6.8 内核:
6.8: 52 PASS / 5 FAIL / 30 SKIP复制
所以不是硬件的锅,不是 QEMU 的锅,是内核版本的锅。这个判断花了我半小时,是全程唯一一个一次就判对的东西。
接下来我干了什么呢?我打开了
git diff v5.10..v6.8 -- arch/x86/kvm/svm/
。
8844 行,
svm.c
、
nested.c
、
svm.h
三个文件。
我从上午翻到下午,一个函数一个函数地看
init_vmcb
、
npf_interception
、
svm_vcpu_reset
、
svm_set_efer
。翻完的结论是——
这些函数两棵树语义等价,差异全是 API 改名和 nested/SEV 这些无关路径
。
冒烟枪不在这个目录里,我在错误的地方挖了一整天。
那个下午我盯着终端,脑子里冒出来的念头特别具体:这活干久了,人是会变笨的。 不是说累,是那种“我明明有一堆经验,但每次都要重新用肉眼把它们排一遍”的钝感。我上一次回合补丁踩过的坑、上上次总结出来的顺序,全都散落在几个 markdown 笔记、几个终端 history、和我不太可靠的记忆里。经验有,但经验不“跟着工具走”。
《kernel-patch-backport(内核补丁回合工具)》 这个 Skill 就是那天之后开始写的。
为什么内核回合这块一直是空白
先解释一个词。回合(backport),指把上游新版本内核里的某个补丁,移植到你正在维护的低版本内核上。稳定内核维护、发行版内核 (比如龙蜥的 ANCK) 、以及所有需要长期支持某个 LTS (Long Term Support,长期支持版本) 的场景,天天都在干这件事。
这件事有大量现成工具吗?有。
git cherry-pick
一行就能跑。
那为什么还是天天翻车?因为翻车的地方从来不在
cherry-pick
那一步。我把一线最常见的三类,连同当时的原话吐槽一起列在这儿:
痛点 1:依赖链失控 —— “怎么越滚越多”
补丁 A 依赖补丁 B,B 依赖 C,C 又动了一个 helper……你以为在回合 1 个补丁,最后回合了 30 个。
本来是修一个空指针,现在我这个分支跟上游差了三十个 commit,评审都没人敢看。
问题的核心是:很多“依赖”根本不是必须回合的依赖。上游改了个函数签名,你改一下调用点就行;上游把代码抽成了 helper,你把改动应用回原位置就行。把这些“可适配的”当成“必须回合的”,雪球就是这么滚起来的——而且滚得越大,风险越高,跟你想要的“稳定”完全背道而驰。
痛点 2:假验证 —— “编译过了,但一行都没编”
这是最阴的一类。两个典型形态:
-
老内核树自己就带着编译错误。你不建基线,编译出来一堆 error,根本分不清哪些是你引入的、哪些是它本来就有的。于是要么在别人的锅上排查半天,要么干脆把自己引入的错误一起忽略了。
-
补丁受某个
CONFIG_XXX保护,而那个 CONFIG 没开。编译完美通过,因为你的新代码一行都没参与编译。
绿了,过了,合入。三周后线上复现,回头一看那个 CONFIG 压根没开。
痛点 3:语义漂移 —— 编译和测试都抓不住的那种错
适配的时候,上游
return -EINVAL
你写成了
return -EIO
。编译过,测试也可能过,但用户态拿到的 errno 变了,行为变了。
更致命的是锁。上游用了
guard(mutex)
(一种自动释放锁的写法),老内核不支持,你得手工展开成
mutex_lock()
/
mutex_unlock()
。这个函数有三条
return
路径,你补了两条。
漏掉的那条就是死锁。 编译不会报,单元测试大概率也碰不到,它会安静地躺在你的稳定内核里,等一个特定的错误分支。
这三类问题的共同点是:它们都不是知识问题,是纪律问题。
每一条我都知道。每一条我都在某个笔记里写过。但在一个具体的、赶时间的回合任务里,我不会每次都想起来把它们全过一遍。
而 Agent 会。这就是我写这个 Skill 的全部动机——把纪律从“我记得”变成“流程强制”。
这个 Skill 到底能干什么
一句话版本:你说“把这个 commit 回合到我们的 6.6 内核”,它带着你走完六个阶段,每一步都不许跳,最后给你一份能直接贴进评审的报告。具体展开是四个能力点。
依赖三分类:治“依赖链失控”
这是我认为最有价值的一条。Skill 强制要求:每一条依赖都必须被归到三类之一,只有 PREREQUISITE 才允许进依赖链。
|
依赖的性质 |
分类 |
处理动作 |
|
只改了函数签名 |
ADAPTABLE |
改调用点,用目标树的老签名 |
|
只是函数/变量改名 |
ADAPTABLE |
用目标树的老名字 |
|
给已有 API 套了层 wrapper |
ADAPTABLE |
直接调底层函数 |
|
把代码抽成 helper |
ADAPTABLE |
把改动应用到原位置 |
|
纯注释、空行、typo |
INCIDENTAL |
跳过 |
|
引入全新结构体/函数 |
PREREQUISITE |
必须回合 |
|
新增字段且目标补丁要用 |
PREREQUISITE |
必须回合 |
关键在于“必须查证”,而不是“看着像”:
# 目标树里到底有没有这个符号?有 = 依赖不成立,整条砍掉git -C <target> grep -n '<symbol_name>' -- '*.c' '*.h'复制
分类完,它会输出一张扩展补丁列表给你确认,一行一个,不允许写“还有 N 个补丁”这种省略:
|
# |
标签 |
短 hash |
Subject |
理由 |
|
1 |
[dependency] |
abc123de |
引入 foo_context 结构体 |
目标补丁要用 |
|
2 |
[requested] |
def456ab |
修复 foo 空指针解引用 |
用户请求的目标补丁 |
|
3 |
[fix-critical] |
789abcde |
修复上条引入的 UAF |
上游后续修复,强烈建议一起回合 |
列表未经你确认,它不会开始 cherry-pick,这是硬性要求。
基线差分:治“假验证”
回合之前,先编一遍,把“老树”自带的错误存下来:
make ARCH=x86_64 -j"$(nproc)" 2>&1 | grep "error:" | sort -u > /tmp/baseline-errors.txt复制
回合之后,只看差集:
make ARCH=x86_64 -j"$(nproc)" 2>&1 | grep "error:" | sort -u \ | diff /tmp/baseline-errors.txt - | grep '^>'复制
无输出 = 无新增错误 = 这一步你是干净的。
这个动作我以前也做,但做得随缘。现在它是阶段 ④ 的第一件事,不是可选项。
针对“CONFIG 没开导致代码没编”,Skill 里给了一个我很喜欢的土办法:
故意在新代码里插一行语法错误,重编,应该报错。不报错,说明这段代码根本没参与编译。验证完记得撤销。
语义等价八条 + 锁配平:治“语义漂移”
八条清单,逐条对着上游原始补丁看:
-
错误码一致 —— 上游
-EINVAL的路径没变成-EIO -
goto 标签映射正确—— 适配后的清理动作与上游等价 -
函数参数含义没错位 —— 老 API 参数顺序不同,实参要跟着调
-
结构体字段确实存在 ——
grep确认,不是靠猜 -
条件判断方向正确 ——
if (!ret)没被写成if (ret) -
边界值一致——<与<=、size与size - 1 -
内存分配 flag 一致——GFP_KERNEL/GFP_ATOMIC(原子上下文用错会 panic) -
无重复定义 —— 没把同一函数定义两遍
外加锁配平:
git diff --cached | grep -cE '^\+.*(mutex_lock|spin_lock|read_lock|write_lock|down_read|down_write)'git diff --cached | grep -cE '^\+.*(mutex_unlock|spin_unlock|read_unlock|write_unlock|up_read|up_write)'复制
这里有个我踩过的坑,值得单独说:正则末尾千万别锚
\(
。因为
spin_lock_irqsave
、
mutex_lock_interruptible
这类变体的括号位置不同,锚了之后 lock 和 unlock 两边同时漏匹配,计数会“虚假配平”——
L == U
显示一切正常。
这比直接报错危险得多。 一个骗你说"没问题"的检查,不如没有检查。
龙蜥 / ANCK 专属适配:这条是我最想展开讲的
通用 backport 教程满大街都是,但它们几乎都默认你在纯
linux-stable
树上操作。在 ANCK 上不是这么回事。
先说怎么区分。
uname -r
带
.an8
/
.an23
后缀的是龙蜥自研的 ANCK
(Anolis Cloud Kernel)
,不带的是 RHCK
(Red Hat Compatible Kernel)
。两者的配置基线和补丁基线完全不同,回合前必须先确认目标是哪一个:
uname -r rpm -q kernel kernel-devel 2>/dev/null复制
为什么必须区分?举个具体的对比。
假设你要回合一个用了
sysfs_emit()
的补丁。查版本表,
sysfs_emit()
是 v5.10 引入的。你的目标树是 5.10 之前的某个 ANCK 基线,于是你按表适配,把它改写成
scnprintf(buf, PAGE_SIZE, ...)
。
这个适配是多余的,而且是有害的。因为发行版内核常常会把上游 helper 单独 backport 到更老的基线上,ANCK 尤其如此。你的树里很可能已经有
sysfs_emit()
了,你手工改写的结果是:代码能跑,但和上游的形态出现了不必要的分歧,下一个人来回合相关补丁时,冲突面积更大。
如果换成
guard(mutex)
这种,误判的代价就不只是“分歧”了——手工展开漏一条 return 路径就是死锁。
所以 Skill 里立了一条硬规矩:
绝不能凭版本印象断定"老内核不支持"。动手适配前,先在目标树里
git grep查一次。git grep -n '#define guard(' -- 'include/linux/*.h'复制有输出 = 支持 = 原样应用,不要适配。
误判的代价是不对称的,这是这条规矩的全部理由:
-
误判为“不支持” → 你做了一次非必要的手工展开,
guard()漏 unlock 就是死锁。编译器不会救你。 -
误判为“支持” → 编译报
implicit declaration,编译器兜住了。
所以宁可多敲一条
git grep
。文档里的版本表只用来缩小排查范围,一律以目标树实测为准。
ANCK 还有第二个特点:它本身已经带了大量自有补丁,上游 commit 在 ANCK 上的冲突率显著高于纯 stable 树。所以 Skill 在冲突处理阶段会先让你看一眼这个文件在目标树上已经被改成什么样了:
git log --oneline <base>..HEAD -- <path>复制
其余龙蜥约定(包管理统一
dnf
不写死
yum
、服务管理用
systemctl
、镜像源优先
mirrors.openanolis.cn
、回合结果提交回社区遵循木兰宽松许可证 v2 且保留上游
Signed-off-by
)也都固化进去了。
真实场景:那个 8844 行的案子,用 Skill 重走一遍
现在回到开头。我用这个 Skill 的流程,把当时那个案子重新走了一遍,看看能省下多少。
以下技术细节(架构代际、根因、上游 commit hash、测试比分)均为实测原值。
Before:我实际走的路(约 3 天)
Day 1
—— 上午进行现象确认。5.10 上 guest 卡死,6.8 正常,这一步没问题。同天下午
误判 ①
:我认为是 CPU triple-fault
(三重故障,CPU 反复重置)
。依据是 QEMU 日志里看到
EIP=0
和 CPU Reset。这是个纯粹的静态推断,我没有验证它。
Day 2
—— 基于误判 ①,我认定问题在 CPU 初始化,于是去 diff
arch/x86/kvm/svm/
。
8844 行,看了一整天,无收获。当天晚上出现误判 ②:我怀疑是 5.10 缺少 Zen5 的 CPU 识别。这次我去查了,结果是打脸:
arch/x86/kernel/cpu/amd.c
里
已经有
family 0x1a
→
X86_FEATURE_ZEN5
的识别代码。
Day 3 —— 终于想起来上 ftrace。
After:数据说话的那 20 分钟
打开 KVM 的
kvm_entry
/
kvm_exit
tracepoint,配合 QEMU
-d int,cpu_reset
,跑 10 秒:
exit_reason 统计: npf 14845 次 ← 全部 interrupt 5 次 ← 定时器 SHUTDOWN 0 次 ← ⚠ triple-fault 会走这里guest rip: 恒为 0xfff0 ← 复位向量,一条指令都没执行exit_info1: 0x1_00000014 ← NPT 层 / 取指 / P=0(页不存在)exit_info2: 0xfffff000 ← 出错的 GPA = 复位向量页QEMU cpu_reset: 仅 2 次正常上电复位(EDX=00b10f10 确认真实硬件) 无反复复位复制
误判 ① 当场出局
。
SHUTDOWN
零次、
cpu_reset
只有正常的两次 —— 根本不是 triple-fault,是
NPT(Nested Page Table,嵌套页表,硬件辅助虚拟化的二级地址翻译)
取指故障死循环。
机制清楚了:vCPU 上电 → 取复位向量第一条指令 → GPA
0xfffff000
的 NPT 翻译失败 →
#NPF
退出 → handler 处理完重新
VMRUN
→ 同一个 GPA 立刻又
#NPF
→ rip 永不前进。
单变量二分:把根因锁死在硬件层
有了正确的现象,接下来是三态对照,一次只动一个变量:
|
配置 |
说明 |
结果 |
|
tdp_mmu=N + npt=1 |
legacy shadow-NPT(5.10 默认) |
❌ TIMEOUT |
|
tdp_mmu=Y + npt=1 |
TDP MMU |
❌ TIMEOUT |
|
npt=0 |
纯软件影子页表,绕开硬件 NPT walker |
✅ PASS |
这张表的信息量很大:
-
切换 MMU 子模式(
tdp_mmuN↔Y) 不改变结果 → 两种 MMU 走的是完全不同的 SPTE 构建代码,都挂 → 排除 TDP MMU 实现 bug、SPTE 保留位、kvm_mmu_max_gfn等一系列假设。 -
只要开硬件 NPT 就挂,关掉就过→ 根因精确锁定在“5.10 对该硬件 NPT 的配置/使能”。
📌
这也直接解释了为什么我 diff
svm/
一整天找不到冒烟枪 —— 因为那不是软件逻辑正确性问题
。
冒烟枪
/* 5.10 */static int get_max_npt_level(void){
return PT64_ROOT_4LEVEL; /* ← 无条件返回 4 级 */}/* 6.8 */static int get_npt_level(void){
return pgtable_l5_enabled() ? PT64_ROOT_5LEVEL : PT64_ROOT_4LEVEL;
}复制
而这台 host
实际运行在 5-level paging(LA57,57 位虚拟地址)下,铁证是 vmalloc 地址
0xff65db72...
—— 4 级分页的内核地址第二字节必为
0xff
,这里是
0x65
,只能是 5 级。
于是:host 是 5 级,5.10 却给 NPT 建了张 4 级表,硬件 NPT walker 按 host 的 LA57 规则把这张 4 级表当 5 级解读 → walk 出垃圾 →
所有 GPA 都
#NPF
(只因 guest 卡在复位向量,所以我只看到
0xfffff000
这一个)。
npt=0
绕开硬件 walker 走软件影子页表,KVM 按 host 的 5 级正确翻译 → 立即 PASS。
完全闭合,而且这根本不是新架构专属问题 —— 任何 5-level paging host 上的 5.10 都会中招。
依赖链:三个补丁,一个都不能少
上游修复是 2021 年的一个 3-patch 系列, 合入 v5.15 (所以 5.10 没有) :
|
# |
标签 |
commit |
Subject |
分类 |
|
1 |
[dependency]
|
746700d21fdf
|
KVM: x86: Allow CPU to force vendor-specific TDP level |
PREREQUISITE —— 给 kvm_configure_mmu() 新增 tdp_forced_root_level 参数,后两个补丁都要用 |
|
2 |
[dependency]
|
cb0f722aff6e
|
KVM: x86/mmu: Support shadowing NPT when 5-level paging is enabled in host
|
PREREQUISITE —— MMU 侧 pml5_root ,host LA57=1 而 guest LA57=0 时构造固定 PML5 顶层
|
|
3 |
[requested] |
43e540cc9f2c |
KVM: SVM: Add 5-level page table support for SVM |
目标补丁 —— get_npt_level() 按 LA57 动态返回 4/5级 |
还有一次翻车,而且正好翻在 Skill 的红线上
我第一次记录这个依赖链的时候,把其中一个 hash 写成了
4995a3685f1b
。
后来逐一核实,发现
那是错的 ——
4995a3685f1b
实际是 "KVM: SVM: Use a separate vmcb for the nested L2 guest",跟 5-level paging 一点关系都没有。是我凭印象记的。
如果我不核实就按这个列表回合,会发生什么?回合进去一个无关的 nested 重构补丁,冲突一大堆,改完还修不好问题 —— 然后我大概率会得出"这个方案不行"的错误结论。
这正是 Skill 里那条“扩展补丁列表必须一行一个、必须逐个查证、未经确认不许 cherry-pick”的由来。 它不是我从教科书上抄的最佳实践,是我自己撞出来的。
📌 Takeaway
|
# |
结论 |
适用范围 |
|
1 |
现象没坐实之前,不要碰 diff。我用 8844 行代码换了一个教训:错误的现象假设会让你在错误的目录里挖一整天。 |
通用 |
|
2 |
单变量二分优先于逐行阅读。npt=0/1一个开关,20 分钟锁死根因;tdp_mmu N/Y 一次对照,排除掉一整类假设。 |
通用 |
|
3 |
依赖链里的每个 hash 都必须核实。凭印象记的 hash 会错,而错的依赖链比没有依赖链更浪费时间。 |
通用 |
|
4 |
5-level paging host + 5.10 KVM = 必挂。若你在维护 5.10 基线且 host 开了 LA57,直接回合上述 3-patch 系列。 |
选型建议 |
|
5 |
急用时的规避手段:modprobe kvm_amd npt=0,纯影子页表,性能差但能跑。 |
应急 |
开发过程与踩坑记录
这部分是我认为对读者最有复用价值的 —— 怎么把散落的经验变成 Agent 能执行的指令。
做减法:从“内核开发助手”砍到“补丁回合”
我最初的想法很大:做一个"内核开发助手",覆盖编译、调试、性能、补丁……
写了两天就写不下去了。 范围太大的 Skill,等于没有 Skill 。 因为 Agent 无法判断什么时候该用它,而每一块的深度都不够,读起来像一本目录。
最后砍到只做“补丁回合”这一件事,并且明确划了边界:
-
✅ 做:依赖分析、依赖链构建、cherry-pick、冲突解决、编译验证、语义核对、报告
-
❌ 不做:内核调试(那是另一个 Skill)、性能调优、内核配置裁剪、CI 集成
边界一旦清楚,文档质量立刻上一个台阶 。 因为你不再需要“照顾”那些边缘场景,可以把每一步都写到能直接照抄执行。
经验怎么变成指令:三条我总结出来的写法
(a) 把“注意 XX”改写成一条能跑的命令。
无效写法:
⚠️ 注意:老内核可能不支持
guard()宏 。
Agent 读完这句话,什么也做不了 —— 它只会继续凭训练数据里的版本印象猜。有效写法是给它一条命令和一个判据:
复制git grep -n '#define guard(' -- 'include/linux/*.h'复制有输出 = 支持 = 原样应用,不要适配。
命令 + 判据 + 动作,三件套齐了,Agent 才能真的执行。
(b) 把“最佳实践”改写成“红线 + 代价” 。
只写“建议建基线”,Agent (和人一样) 赶时间的时候就会跳过。所以我把每条规矩都配上了 跳过的代价:
不建基线 → 老树自带的错误会被误算成回合引入的 → 浪费大量时间排查。 基线是第一步,不是可选项。
写清楚代价,“要不要跳过”这个判断题就消失了。
(c) 把易错点做成“不对称代价”表 。
这是我最满意的一条设计。前面龙蜥 / ANCK 专属适配讲过:判错方向不同,代价差着一个量级。把这个不对称 显式写出来,Agent 就知道该往哪边保守。
选了什么,放弃了什么
|
决策 |
选择 |
理由 |
|---|---|---|
|
是否内置全自动回合 |
❌ 放弃 |
依赖链 必须人工确认。全自动 = 把最需要判断的一步交给最不该做判断的角色 |
|
是否依赖私有 CLI / 内部服务 |
❌ 放弃 |
只用
|
|
冲突解决策略的优先级 |
✅ 接口适配 > 手工套用 > 回合前置补丁 |
直接对应“依赖链失控”这个痛点:最后一条最省事,也最容易滚雪球,所以放最后 |
|
验证结论的粒度 |
✅ HIGH / MEDIUM / LOW / FAIL 四档 |
二值化的“过 / 不过”会逼人把 60 分的结果说成“过了”。四档给了"我不确定"一个诚实的位置 |
关于最后一条,规则是: 只有 HIGH 和 MEDIUM 允许进入下一个补丁,LOW(改动大、自动检查覆盖不足)必须人工逐行复核后重新定档,FAIL 直接停。
三个具体的坑
坑 1:
make M=<dir>
是外部模块入口,不能用在树内子目录
。
我一开始在脚本里写了
make M=drivers/net/ethernet/xxx
。它
不报错,但也
什么都没编 —— 因为
M=
是外部模块构建入口,不读树内 Makefile 的
obj-y
规则。
编译“通过”其实一行没编。这是最典型的假验证,也是最难发现的一种。
树内一律用
make dir/
,
末尾斜杠不可省。
坑 2:锁配平正则锚了
\(
,导致虚假配平
。
前面语义等价八条 + 锁配平:治语义“漂移”讲过。教训是: 一个会撒谎的检查,比没有检查更危险。
坑 3:重复定义检查把前向声明误报了 。
统计函数定义次数时,函数原型(以分号结尾的那行)也会被算进去,于是"声明 + 定义"被报成"重复定义 2 次"。加一个
grep -v ';$'
排除掉:
n=$(grep -rhE "^[a-zA-Z_].*\b$f\b\s*\(" <dir>/*.c | grep -vc ';\s*$')复制
误报会摧毁工具的可信度。 一个天天喊狼来了的检查,用户三次之后就会开始无脑忽略它 —— 包括真的那次。
后续规划
短期 roadmap
都是我自己确实需要、也确实能做的,不画大饼:
1.补齐 ANCK 高频冲突模式 —— 目前 references/conflict-patterns.md 里的适配写法偏通用。ANCK 因自带补丁多,有一批特有的冲突形态,我打算按子系统整理进去。
2. precommit-check.sh 支持 --range —— 现在只能查暂存区或单个 commit,一个系列回合完想整体自检还得写循环。
3.补一个 KVM / 虚拟化方向的完整案例 —— 就是本文这个。现有的 examples/ 是网络驱动,覆盖不到"根因不在补丁本身"这类更麻烦的场景。
4. git grep 查证结果缓存 —— 同一个 helper 在一次会话里会被反复查,可以缓存掉。
说点个人的小期待——如果将来有机会被社区纳入预装 Skill 池,让新同学开箱即用,那自然是再好不过。当然最终还是要看社区的需要和评估,我能做的就是先把东西本身打磨到位。
写在最后
我想再说一遍开头那个念头:这活干久了,人是会变笨的。
不是因为工作本身没价值 —— 恰恰相反。而是因为在传统模式下,你的经验只能存在三个地方:你的脑子、你的私人笔记、和你偶尔在群里回答别人问题的那几条消息。它们都不会自动跟着工具走。
于是每一个新人都要把你踩过的坑重踩一遍。每一次你自己赶时间,也会把自己总结的纪律跳过一遍。经验没有复利。
Agent Skill 这个形态第一次让我觉得,经验是可以跟着工具走的。我把“必须先建基线”写进去,它就每次都会先建基线;我把“guard() 必须先 git grep 查证”写进去,它就不会再凭印象猜版本 —— 它比我更有纪律,因为它不会累,也不会赶时间。
这大概就是“知识平权”最朴素的一种形式:不是把知识发出去,而是把知识变成默认行为。
我的 8844 行 diff 白看了,但如果这个 Skill 能让下一个人少看 8844 行,这笔账就算划得来。
也欢迎你把自己踩过的坑写成 Skill 投到 SkillHub 上来。 你觉得“这不就是常识吗”的那些东西,往往正是别人正在花三天时间重新踩的坑。
附:术语表
|
术语 |
说明 |
|
回合 / backport |
把上游新版本的补丁移植到低版本内核 |
|
LTS |
Long Term Support,长期支持版本 |
|
ANCK |
Anolis Cloud Kernel,龙蜥自研云内核 |
|
cherry-pick |
git 命令,把某个 commit 单独应用到当前分支 |
|
UAF |
Use-After-Free,释放后使用,一类内存安全漏洞 |
|
NPT |
Nested Page Table,嵌套页表,硬件辅助虚拟化的二级地址翻译机制 |
|
#NPF |
Nested Page Fault,NPT 翻译失败触发的 VM exit |
|
5-level paging / LA57 |
五级页表,支持 57 位虚拟地址(4 级为 48 位) |
|
triple-fault |
三重故障,CPU 处理异常时再次异常,导致强制重置 |
|
GPA |
Guest Physical Address,客户机物理地址 |
相关链接:
内核补丁回合工具 (kernel-patch-backport) :
https://skillhub.openanolis.cn/skill/kernel-patch-backport
Skillhub 官网链接 :
https://skillhub.openanolis.cn
龙蜥社区 cloud-kernel:
https://gitee.com/anolis/cloud-kernel
相关文章推荐:
从此告别重复劳动,百款开源项目适配经验提纯成 AI Agents | 龙蜥 SkillHub 精选
教了 Agent 一百遍工程规矩,我干脆把它写成了 Skill | 龙蜥 Skillhub 精选
敲了十年 vmstat,我把排查经验塞进了一个 AI Skill | 龙蜥 Skillhub 精选
一句话搞定 PG 集群部署和管理 | 龙蜥 Skillhub 精选
龙蜥社区 Skill 征集活动——
「Skill 创造营」
上线以来响应热烈。截至目前,龙蜥 SkillHub 已收到覆盖安全、系统运维、AI 推理、数据库等多个领域,一个面向 Infra 的 AI 技能生态正在加速成型。「Skill 创造营」持续征集中,诚挚欢迎每一位开发者提交你的 Skill 与最佳实践。如果你有感兴趣的方向或者关于 SkillHub 的问题,欢迎通过下方链接反馈给我们。
SkillHub 用户需求收集链接: https://alidocs.dingtalk.com/notable/share/form/v014jKqm0b74KdjLnw1_f22ghuX_M7AJs3D
—— 完 ——