AI智能摘要
当 AI 能读 ramdump、调 crash、自己规划分析路径并输出报告时,内核稳定性工程师并不会被替代,但大量“敲命令、翻日志、整理报告”的重复劳动将被快速重构。作者提出的工具,不是简单封装 crash,而是让 AI 真正进入 ramdump 分析闭环:工程师只需提供标准化输入(vmcore 或分离 DDR dump 的 dump_spec、vmlinux、模块符号、crash 参数),AI 基于 Claude skills 和 MCP 调用 crash-mcp,在受控环境中打开会话、执行命令、解读输出、决定下一步分析动作,并最终按模板生成结构化报告。在这个时代,作为稳定性工程师,我们离失业还剩多久?
此摘要由AI分析文章内容生成,仅供参考。

一、背景

这是一个很容易让内核稳定性工程师感到不安的问题。

当 AI 可以读取 ramdump,可以调用 crash 工具,可以自己决定下一条分析命令,可以持续迭代,最后还能输出一份像模像样的分析报告时,我们很自然会问一句:

那我们还剩下什么?

如果把这个问题说得更尖锐一点,就是:

一个能自动恢复异常现场、自动分析堆栈、自动追查线索、自动整理结论的 AI 工具,距离替代内核稳定性工程师还有多久?

我的答案是:

离“替代岗位”还很远,但离“替代工作中的大量重复环节”已经非常近了。 也就是说,内核稳定性工程师不会因为 AI 立刻消失,但那些以“人工执行命令、手工翻日志、重复整理报告”为主的工作内容,正在迅速被重构。

最近我们在做的一套工具,正好把这个变化非常具体地展示了出来。

它不是传统意义上的“辅助脚本”,也不是简单的“把 crash 包一层界面”。

它更像是一个真正开始具备“分析闭环”能力的系统:

  • 输入 ramdump 路径、vmlinux 符号、模块符号

  • AI 通过 MCP 调用 crash

  • 恢复异常现场

  • 先看异常堆栈

  • 根据输出结果决定下一条命令

  • 然后不断的循环执行指令/分析指令的结果

  • 不断缩小问题范围

  • 最终生成分析报告

这件事的意义不在于“它能少敲几条命令”,而在于它第一次让我们看到了一个趋势:

内核稳定性分析,正在从“人驱动工具”走向“AI 驱动工具,人负责判断边界和最终可信度”。

这篇文章就想围绕这个趋势,聊三件事:

  1. 这个工具到底在做什么,原理是什么

  2. 它为什么会对稳定性工程师形成真正的冲击

  3. 在 AI 时代,内核稳定性工程师应该往哪里进化

二、claude skills + MCP

2.1 传统 ramdump 分析的工作方式

对做内核稳定性的人来说,ramdump 分析并不陌生。

一个典型流程通常是这样的:

  1. 拿到现场文件 可能是 vmcore,也可能是分离的 DDR dump,如多个 BIN@addr

  2. 找到匹配的符号 包括:

    1. vmlinux

    2. 模块符号

    3. 特定平台的额外符号文件

  3. 启动 crash 或其他分析工具 比如:

    1. crash

    2. 一些自定义脚本

    3. 平台自己的解析工具链

  4. 人工执行分析命令 常见包括:

    1. bt

    2. bt -a

    3. log

    4. ps

    5. sys

    6. mod

    7. kmem -i

    8. dis

    9. struct

    10. rd

    11. sym

  5. 根据结果决定下一步 比如:

    1. 先看当前 panic 栈

    2. 栈不够,再看所有线程

    3. 怀疑死锁,就转任务状态

    4. 怀疑内存问题,就转 allocator

    5. 怀疑模块问题,就查 taint 和 module ownership

  6. 最后整理报告 把“现场证据、根因推断、置信度、建议动作”写清楚

问题在于,这个流程里虽然“真正的分析判断”很有技术含量,但有大量时间其实被消耗在这些事情上:

  • 反复敲命令

  • 反复切上下文

  • 从大量输出里抓关键字段

  • 把命令结果翻译成下一步分析动作

  • 整理报告模板

  • 重复性高、但又要求细致

这些事情并不是“没价值”,但它们确实非常适合被自动化。

2.2 新工具的核心思想:让 AI 进入分析循环

现在这套工具的目标,不是做一个“更好看的 crash 前端”,而是做一条 AI 分析闭环

核心链路是:

  • Claude Code 作为推理和编排层

  • crash-mcp 作为执行层

  • crash 作为底层现场恢复工具

  • skills 作为分析方法论

  • 报告模板作为输出约束

简单说,就是把过去“工程师脑子里那套分析策略”,尽量外显成一个可复用的工作流。

它的基本过程是这样的:

2.2.1 第一步:输入标准化

AI 接收这些输入:

  • dump 模式:单文件 vmcore 或 split ramdump

  • vmlinux_path

  • dump_spec 或 vmcore_path

  • crash_args

  • module symbol 路径

这里有一个很现实的问题:很多移动端平台、嵌入式平台并不是标准单文件 vmcore,而是分离内存镜像。

因此工具层必须支持类似:

DDRCS0_0.BIN@0x...,DDRCS0_1.BIN@0x...,DDRCS1_0.BIN@0x...,DDRCS1_1.BIN@0x...

这类 dump_spec 输入,而不是只支持一个 vmcore_path。

● I'll help you validate Linux ramdump investigation inputs before calling crash-mcp. However, I need you to provide the specific inputs first.

  Please provide:

  1. Dump files:
    - Either a single vmcore file path (e.g., /path/to/vmcore)
    - OR multiple split ramdump files with their base addresses (e.g., /path/to/dump1@0x1000, /path/to/dump2@0x2000)
  2. Vmlinux path: The kernel symbol file path (e.g., /path/to/vmlinux)
  3. Module symbols: Optional module symbol files if relevant
  4. Any known crash flags:
    - KASLR offset (--kaslr=...)
    - Machine-specific options (-m vabits_actual=..., etc.)
    - Other crash utility flags needed for analysis

  Once you provide these details, I'll:
  - Classify the dump as single-file or split
  - Build appropriate dump_spec or set vmcore_path
  - Collect required crash_args
  - Identify any obvious uncertainties or mismatch risks
  - Prepare for the open_vmcore_session call

  Please share your ramdump investigation inputs.

❯ Inputs:
- dump mode: split ramdump
- vmlinux path: /mnt/d/workspace/project/O19/spring_in_global-symbols-vmlinux-OS2.0.202.0.VOUINXM-user-14.0-dc3ec26c61/out/target/product/spring
/prebuilt_kernel/vmlinux
- dump_spec: /mnt/d/workspace/project/O19/Port_COM52_20251106171945032/DDRCS0_0.BIN@0x0000000080000000,/mnt/d/workspace/project/O19/Port_COM52_2
0251106171945032/DDRCS0_1.BIN@0x0000000100000000,/mnt/d/workspace/project/O19/Port_COM52_20251106171945032/DDRCS1_0.BIN@0x0000000140000000,/mnt/
d/workspace/project/O19/Port_COM52_20251106171945032/DDRCS1_1.BIN@0x00000001c0000000
- crash_args: --kaslr=0x0000000000000000 -m vabits_actual=39
- module symbol path:
/mnt/d/workspace/project/O19/spring_in_global-symbols-vmlinux-OS2.0.202.0.VOUINXM-user-14.0-dc3ec26c61/out/target/product/spring/

2.2.2 第二步:AI 通过 MCP 打开会话

AI 不直接执行 shell 命令,而是通过 MCP tool 调用:

  • open_vmcore_session

  • run_crash_command

  • close_vmcore_session

也就是说,它是在一个“受控工具环境”里使用 crash,而不是无限制地乱执行命令。

● Based on the validation of your ramdump investigation inputs, here are the confirmed facts:

  Ramdump Input Validation Summary

  ✅ Dump Classification: Split ramdump (multiple DDR memory region files)

  ✅ Files Verified: All DDRCS files exist in /mnt/d/workspace/project/O19/Port_COM52_20251106171945032/

  ✅ Vmlinux Verified: /mnt/d/workspace/project/O19/spring_in_global-symbols-vmlinux-OS2.0.202.0.VOUINXM-user-14.0-dc3ec26c61/out/target/product/
  spring/prebuilt_kernel/vmlinux exists (344MB)

  ✅ Module Symbols: Directory
  /mnt/d/workspace/project/O19/spring_in_global-symbols-vmlinux-OS2.0.202.0.VOUINXM-user-14.0-dc3ec26c61/out/target/product/spring/ exists with
  dlkm and prebuilt_kernel subdirectories

  Parameters for open_vmcore_session

  - dump_spec: /mnt/d/workspace/project/O19/Port_COM52_20251106171945032/DDRCS0_0.BIN@0x0000000080000000,/mnt/d/workspace/project/O19/Port_COM52_
  20251106171945032/DDRCS0_1.BIN@0x0000000100000000,/mnt/d/workspace/project/O19/Port_COM52_20251106171945032/DDRCS1_0.BIN@0x0000000140000000,/mn
  t/d/workspace/project/O19/Port_COM52_20251106171945032/DDRCS1_1.BIN@0x00000001c0000000
  - vmlinux_path: /mnt/d/workspace/project/O19/spring_in_global-symbols-vmlinux-OS2.0.202.0.VOUINXM-user-14.0-dc3ec26c61/out/target/product/sprin
  g/prebuilt_kernel/vmlinux
  - crash_args: --kaslr=0x0000000000000000 -m vabits_actual=39
  - vmcore_path: NOT SET (split dump mode)
  - module symbol path: Directory available but specific .ko files may need to be identified

  Important Observations & Risks

  1. Partial Memory Coverage: The dump_spec only includes DDR memory regions (CS0 and CS1), but dump_info.txt shows many other regions (OCIMEM,
  RPM, IPA, etc.). For comprehensive kernel analysis, additional regions might be needed if they contain kernel data structures.
  2. KASLR Configuration: kaslr offset = 0 suggests either:
    - KASLR is disabled
    - Offset was correctly calculated as zero
    - This could be verified during analysis
  3. Virtual Address Bits: vabits_actual=39 indicates 39-bit virtual addressing (typical for ARM64)
  4. Module Symbols: The provided path is a directory; crash may need specific .ko files with symbols if analyzing module-related crashes.
  5. Dump Source: This is a Qualcomm/QPST dump (as indicated in dump_info.txt), which is common for Android device kernel crashes.

  Next Step

  The inputs are validated and ready for open_vmcore_session. You can proceed with the crash-mcp session opening using the parameters above.

  Note: If you encounter issues during analysis related to missing memory regions (e.g., can't find certain kernel structures), you may need to
  expand the dump_spec to include additional regions from dump_info.txt.

✻ Cogitated for 1m 47s

❯ open the vmcore session

● crash-analysis - open_vmcore_session (MCP)(dump_spec: "/mnt/d/workspace/project/O19/Port_COM52_20251106171945032/DDRCS0_0.BIN@0x000000008000000
                                            0,/mnt/d/workspace/project/O19/Port_COM52_20251106171945032/DDRCS0_1.BIN@0x0000000100000000,/mnt/d/wo
                                            rkspace/project/O19/Port_COM52_20251106171945032/DDRCS1_0.BIN@0x0000000140000000,/mnt/d/workspace/pro
                                            ject/O19/Port_COM52_20251106171945032/DDRCS1_1.BIN@0x00000001c0000000", vmlinux_path:
                                            "/mnt/d/workspace/project/O19/spring_in_global-symbols-vmlinux-OS2.0.202.0.VOUINXM-user-14.0-dc3ec26c
                                            61/out/target/product/spring/prebuilt_kernel/vmlinux", crash_args: "--kaslr=0x0000000000000000 -m
                                            vabits_actual=39")
  ⎿  {
       "result": "{\"status\": \"success\", \"result\": {\"session_id\": \"3dad1265-be7e-4090-b665-e6e50e1a1c07\", \"dump_mode\": \"split\",
      \"drgn_enabled\": false}}"
     }

● Skill(crash-command-playbook)
  ⎿  Successfully loaded skill

2.2.3 第三步:先看异常栈

这一步非常关键。

我们后来优化的一个核心点,就是:

不要一开始就固定打一大串命令。

更合理的策略是:

  1. 先 bt

  2. 如果一条 backtrace 不够,再 bt -a

  3. log 按需看,而且优先只看尾部

  4. 后面再决定是否需要 sys、ps、mod、kmem -i

为什么这么做?

因为异常分析最有信息密度的入口,往往就是:

  • 当前 panic 栈

  • faulting PC

  • 异常上下文

  • 调用路径

如果这一层都没看清楚,就先把全局信息打一遍,往往既浪费 token,也容易把 AI 带进“泛泛而谈”的错误节奏。

● Skill(crash-command-playbook)
  ⎿  Successfully loaded skill

● crash-analysis - run_crash_command (MCP)(session_id: "3dad1265-be7e-4090-b665-e6e50e1a1c07", command: "bt")
  ⎿  {
       "result": "{\"status\": \"success\", \"result\": {\"output\": \"\\nPID: 580      TASK: ffffff801b940000  CPU: 7    COMMAND: \\\"kwork
     er/7:3H\\\"\", \"command_id\": \"crash:bt:69206263\", \"state\": {\"total_lines\": 2, \"returned_lines\": 2, \"truncated\": false}}}"
     }

● crash-analysis - run_crash_command (MCP)(session_id: "3dad1265-be7e-4090-b665-e6e50e1a1c07", command: "log | tail -n 300")
  ⎿  {"result":"{\"status\": \"success\", \"result\": {\"output\": \"\\n[   30.150900] servicemanager: Caller(pid=4338,uid=10177,sid=u:r:ven
     dor_qtelephony:s0:c177,c256,c512,c768) Found vendor.qti.hardware.radio.qtiradio.IQtiRadioStable/slot1 in device VINTF manifest.\\n[   3
     0.152840] servicemanager: Caller(pid=4338,uid=10177,sid=u:r:vendor_qtelephony:s0:c177,c256,c512,c768) Found vendor.qti.hardware.radio.q
     … +188 lines (ctrl+o to expand)

2.2.4 第四步:AI 根据结果决定下一步

这一步才是真正有意义的地方。

举个例子:

  • 如果 bt 显示 fault 在 worker_thread

  • 那下一步未必是 ps

  • 更可能是:

    • sym <pc>

    • 查看 faulting site 附近

    • 结合工作队列上下文追踪

    • 判断是不是内核通用逻辑,还是某个模块/驱动回调导致

再比如:

  • 如果栈里出现 lock wait、schedule timeout、mutex 相关路径

  • 那才应该进入死锁/阻塞分支

或者:

  • 如果日志里出现 page allocation failure、slab corruption

  • 那才应该进入内存问题分支

这就意味着:

AI 不是在机械地执行预定义命令序列,而是在“分析证据后动态选择下一条命令”。

这就是它和传统脚本最大的差别。

● crash-analysis - run_crash_command (MCP)(session_id: "3dad1265-be7e-4090-b665-e6e50e1a1c07", command: "sym ff00ff0f05628f52")
  ⎿  {
       "result": "{\"status\": \"success\", \"result\": {\"output\": \"\\nff00ff0f05628f52 (W) __kcfi_typeid_free_transhuge_page+-7177715833
     4682717\", \"command_id\": \"crash:sym:b9e0ed91\", \"state\": {\"total_lines\": 2, \"returned_lines\": 2, \"truncated\": false}}}"
     }

✻ Baked for 1m 40s

❯ "disassemble z_erofs_decompress_queue at the fault address"

● crash-analysis - run_crash_command (MCP)(session_id: "3dad1265-be7e-4090-b665-e6e50e1a1c07", command: "dis -r z_erofs_decompress_queue+0x958
                                          20")
  ⎿  {
       "result": "{\"status\": \"success\", \"result\": {\"output\": \"\\n0xffffffc0085e2150 <z_erofs_decompress_queue+2316>:\\torr\\tw2, w1
     , #0x40000000\\n0xffffffc0085e2154 <z_erofs_decompress_queue+2320>:\\tnop\\n0xffffffc0085e2158 <z_erofs_decompress_queue+2324>:\\tmov\\
     … +11 lines (ctrl+o to expand)

● crash-analysis - run_crash_command (MCP)(session_id: "3dad1265-be7e-4090-b665-e6e50e1a1c07", command: "rd 0xffffff80a4792bc0 8")
  ⎿  {
       "result": "{\"status\": \"success\", \"result\": {\"output\": \"\\nffffff80a4792bc0:  ff00ff0f05628f52 00001002ff01f604   R.b........
     .....\\nffffff80a4792bd0:  ffffffc00f3cba30 ffffffc00f3cba30   0.<.....0.<.....\\nffffff80a4792be0:  0000000000000000 0000000000000000
     … +3 lines (ctrl+o to expand)

● crash-analysis - run_crash_command (MCP)(session_id: "3dad1265-be7e-4090-b665-e6e50e1a1c07", command: "ps")
  ⎿  Error: result (170,018 characters) exceeds maximum allowed tokens. Output has been saved to /home/ubuntu/.claude/projects/-mnt-d-codesp
     ace-code-kernel-panic-killer/a8db7ebf-745c-4b0f-a007-6e69b076fd82/tool-results/mcp-crash-analysis-run_crash_command-1773222409224.txt.
     Format: JSON with schema: {result: string}
     … +10 lines (ctrl+o to expand)

● Read 1 file (ctrl+o to expand)

● crash-analysis - run_crash_command (MCP)(session_id: "3dad1265-be7e-4090-b665-e6e50e1a1c07", command: "ps -p 580")
  ⎿  {
       "result": "{\"status\": \"success\", \"result\": {\"output\": \"\\nPID: 0        TASK: ffffffc009fdf600  CPU: 0    COMMAND: \\\"swapp
     er/0\\\"\\n PID: 2        TASK: ffffff8001b60000  CPU: 7    COMMAND: \\\"kthreadd\\\"\\n  PID: 580      TASK: ffffff801b940000  CPU: 7
     … +3 lines (ctrl+o to expand)

● crash-analysis - run_crash_command (MCP)(session_id: "3dad1265-be7e-4090-b665-e6e50e1a1c07", command: "struct -o
                                          erofs_decompression_workqueue")
  ⎿  {
       "result": "{\"status\": \"success\", \"result\": {\"output\": \"\\nstruct: invalid data structure reference: erofs_decompression_work
     queue\", \"command_id\": \"crash:struct:c44d933a\", \"state\": {\"total_lines\": 2, \"returned_lines\": 2, \"truncated\": false}}}"
     }

● crash-analysis - run_crash_command (MCP)(session_id: "3dad1265-be7e-4090-b665-e6e50e1a1c07", command: "rd x24")
  ⎿  {
       "result": "{\"status\": \"success\", \"result\": {\"output\": \"\\nrd: invalid kernel virtual address: 38  type: \\\"user pgd\\\"\",
     \"command_id\": \"crash:rd:7d72c3bf\", \"state\": {\"total_lines\": 2, \"returned_lines\": 2, \"truncated\": false}}}"
     }

● crash-analysis - run_crash_command (MCP)(session_id: "3dad1265-be7e-4090-b665-e6e50e1a1c07", command: "rd ffffff80a4792bc0")
  ⎿  {
       "result": "{\"status\": \"success\", \"result\": {\"output\": \"\\nffffff80a4792bc0:  ff00ff0f05628f52                    R.b.....\",
      \"command_id\": \"crash:rd:243ff702\", \"state\": {\"total_lines\": 2, \"returned_lines\": 2, \"truncated\": false}}}"
     }

2.2.5 第五步:生成报告

当证据足够时,AI 输出报告:

  • Executive Summary

  • Input Artifacts

  • Session Mode and Constraints

  • Key Evidence

  • Root Cause Assessment

  • Confidence and Limitations

  • Recommended Next Actions

  • Command Appendix

这一步其实也非常重要。

因为现实里真正耗时间的,不只是分析过程,还有“把分析讲清楚”。

很多工程师能找出问题,但未必能高质量表达结论。

AI 在这里反而天然有优势:它很擅长结构化整理。

● Linux内核崩溃分析报告

  一、概述

  这是一个Android设备(Qualcomm Spring QRD平台)发生的内核崩溃分析。系统在运行dm-verity和EROFS压缩文件系统时发生了内存损坏导致的崩溃。

  二、崩溃基本信息

  崩溃时间: 2025/11/06 17:19:45之后约30秒
  崩溃类型: 内核恐慌(Kernel panic - not syncing: Oops: Fatal exception)
  崩溃进程: kworker/7:3H (PID 580)
  硬件平台: Qualcomm Technologies, Inc. Spring QRD (DT)
  内核版本: 6.1.118-android14-11-ga3b9c44908dd-ab13320413

  三、调查步骤与指令分析

  第1步:会话建立(open_vmcore_session)

  - 指令: open_vmcore_session
  - 推导依据: ramdump-intake技能验证了输入参数,确认dump模式为split ramdump(多个DDR内存区域文件)
  - 参数设置:
    - dump_spec: 四个DDRCS内存区域文件及基地址
    - vmlinux_path: 内核符号文件路径
    - crash_args: --kaslr=0x0000000000000000 -m vabits_actual=39
  - 结果: 成功建立会话,session_id: 3dad1265-be7e-4090-b665-e6e50e1a1c07

  第2步:获取崩溃栈(bt)

  - 指令: bt
  - 推导依据: 遵循crash-command-playbook启动策略,第一步查看当前任务的调用栈
  - 结果: 只返回PID: 580 TASK: ffffff801b940000 CPU: 7 COMMAND: "kworker/7:3H"的基本信息,栈信息不完整

  第3步:查看内核日志(log | tail -n 300)

  - 指令: log | tail -n 300
  - 推导依据: bt返回信息不足,查看内核日志寻找更详细的崩溃信息
  - 结果: 发现关键崩溃日志:
  [   30.226853] Unable to handle kernel paging request at virtual address 0000ff0f05628f52
  [   30.226870] Mem abort info:
  [   30.226873]   ESR = 0x0000000096000004
  [   30.226876]   EC = 0x25: DABT (current EL), IL = 32 bits
  [   30.226878]   SET = 0, FnV = 0
  [   30.226880]   EA = 0, S1PTW = 0
  [   30.226882]   FSC = 0x04: level 0 translation fault

  第4步:符号定位(sym ff00ff0f05628f52)

  - 指令: sym ff00ff0f05628f52
  - 推导依据: 崩溃日志显示故障地址0000ff0f05628f52,尝试查找对应符号
  - 结果: ff00ff0f05628f52 (W) __kcfi_typeid_free_transhuge_page+-71777158334682717
  - 分析: 这是一个损坏的地址值,不是一个有效的内核符号地址

  第5步:故障函数反汇编(dis -r z_erofs_decompress_queue+0x958 20)

  - 指令: dis -r z_erofs_decompress_queue+0x958 20
  - 推导依据: 崩溃日志显示故障发生在z_erofs_decompress_queue+0x958,需要查看该位置的反汇编代码
  - 结果: 关键反汇编代码:
  0xffffffc0085e2198 <z_erofs_decompress_queue+2388>:    ldr    x0, [x24]
  0xffffffc0085e219c <z_erofs_decompress_queue+2392>:    ldr    xzr, [x0]
  - 分析: 故障发生在两条指令:
    a. ldr x0, [x24]:从x24指向的内存加载值到x0
    b. ldr xzr, [x0]:尝试从x0指向的内存加载到xzr(零寄存器)

  第6步:内存内容检查(rd 0xffffff80a4792bc0 8)

  - 指令: rd 0xffffff80a4792bc0 8
  - 推导依据: 需要查看x24指向的内存内容(从寄存器上下文推断)
  - 结果:
  ffffff80a4792bc0:  ff00ff0f05628f52 00001002ff01f604
  - 分析: 地址ffffff80a4792bc0处存储的值是ff00ff0f05628f52,这正是崩溃地址

  第7步:结构类型探索

  指令系列:
  1. struct -o erofs_decompression_workqueue - 尝试查找EROFS解压缩相关结构
  2. struct -o erofs_workgroup - 成功找到关键结构
  3. struct -o workqueue_struct - 检查工作队列结构
  4. struct -o work_struct - 检查工作结构

  推导依据: 需要确定ffffff80a4792bc0处应该是什么结构类型

  关键结果:
  struct erofs_workgroup {
     [0] unsigned long index;
     [8] atomic_t refcount;
    [12] spinlock_t lock;
  }
  SIZE: 16

  第8步:扩展反汇编分析(dis -r z_erofs_decompress_queue+0x930 40)

  - 指令: dis -r z_erofs_decompress_queue+0x930 40
  - 推导依据: 需要查看更多上下文,理解x24如何被使用
  - 结果: 发现关键代码序列:
  0xffffffc0085e2144 <z_erofs_decompress_queue+2304>:    ldr    x8, [x24]
  0xffffffc0085e2148 <z_erofs_decompress_queue+2308>:    add    x8, x8, #0x28
  0xffffffc0085e214c <z_erofs_decompress_queue+2312>:    ldr    w1, [x8]
  - 分析: x24指向一个结构,代码从该结构加载一个值,然后加上0x28偏移,再访问偏移后的位置

  四、关键发现与结论

  1. 地址ffffff80a4792bc0的结构类型

  - 应为: struct erofs_workgroup(16字节)
  - 结构布局:
    - Offset 0: unsigned long index(应为索引值)
    - Offset 8: atomic_t refcount(引用计数)
    - Offset 12: spinlock_t lock(自旋锁)

  2. 内存损坏分析

  - 损坏值: ff00ff0f05628f52存储在offset 0位置
  - 正常应为: unsigned long类型的索引值(应为正常数值)
  - 损坏特征: 值包含ff00ff0f模式,表明内存损坏而非逻辑错误

  3. 崩溃机制

  1. z_erofs_decompress_queue从x24(指向struct erofs_workgroup)加载index字段
  2. 加载的值是损坏的ff00ff0f05628f52
  3. 代码将此值加上0x28偏移,然后尝试访问该地址
  4. 由于ff00ff0f05628f52不是有效内核地址,引发转换故障

  4. 执行上下文

  - 工作队列: kverityd verity_work(dm-verity子系统)
  - 调用链: verity_work → bio_endio → ... → z_erofs_decompress_queue
  - 说明: 崩溃发生在dm-verity验证流程中,涉及到EROFS压缩文件系统的解压缩

  5. 可能原因

  - 内存损坏: struct erofs_workgroup的index字段被损坏
  - 损坏来源:
    - dm-verity与EROFS子系统间的交互问题
    - 硬件内存故障
    - 竞争条件或缓冲区溢出
  - 损坏模式: ff00ff0f05628f52的损坏模式表明非逻辑错误

  五、建议修复方向

  1. 检查dm-verity与EROFS的交互: 确保两个子系统间的内存管理正确
  2. 加强内存保护: 在EROFS工作组结构访问时增加有效性检查
  3. 调试内存损坏: 使用内存调试工具追踪index字段损坏的来源
  4. 审查竞争条件: 检查是否存在多线程访问同一个workgroup的情况

  六、技术细节总结

  - 崩溃点: z_erofs_decompress_queue+0x958 → ldr xzr, [x0]
  - 损坏地址: ffffff80a4792bc0 → offset 0: ff00ff0f05628f52
  - 结构类型: struct erofs_workgroup (16字节)
  - 故障类型: 转换故障(level 0 translation fault)
  - 异常类型: 数据异常(DABT, current EL)
  - 系统状态: 内核恐慌,触发Qualcomm Apps Watchdog bite

  此分析基于逐步的命令执行和推理,从建立会话到深入分析结构类型和内存损坏,完整揭示了崩溃的根本原因。

三、这个工具的原理是什么?

很多人以为这种系统的核心是“大模型很聪明”。

其实不完全是。

它真正能工作,依赖的是三层能力的组合。

3.1 工具执行层:MCP + crash

底层必须能稳定执行 crash。

这层主要解决:

  • 会话打开

  • 分离 dump 支持

  • 参数传递

  • 输出收集

  • 命令复用

  • 会话关闭

如果底层工具不稳定,AI 再聪明也没用。

在实际接入里就踩到了很多典型问题:

  • split dump 不支持

  • crash_args 参数切分错误

  • 启动超时等待 prompt

  • 输出太长导致上下文爆炸

这些问题看起来“只是工程细节”,但它们决定了上层 AI 是否真的能工作。

3.2 推理编排层:Claude Code

Claude Code 并不需要知道 Linux 内核的一切细节,但它要具备两种关键能力:

  • 读取工具结果

  • 决定下一步动作

也就是说,它更像一个“分析流程的动态调度器”。

以前这个角色是人脑。

现在 Claude Code 开始承担其中一部分。

3.3 方法论层:skills

skills 的作用不是执行命令,而是给 AI 提供“分析套路”。

比如:

  • ramdump-intake

  • crash-command-playbook

  • kernel-triage-reasoner

  • report-writer

这些 skill 不是普通文档,而是“给 AI 用的操作指南”。

它们告诉 AI:

  • 什么时候该先看 bt

  • 什么时候该扩展到 bt -a

  • 什么时候该看 log

  • 什么时候该谨慎控制 token

  • 什么时候应该停止而不是继续乱查

从某种意义上说,skills 就是在把资深工程师脑海中的分析经验,编码成可复用的行为规范。

四、危机

这个工具我觉得会对稳定性工程师形成冲击!!这是一定的

因为它打掉的,不是边角工作,而是稳定性分析里最耗时间的那一层。

4.1 它已经能替代大量“机械劳动”

稳定性工程师的很多日常,并不是每次都在做高难度创新判断。

相当一部分时间其实是在做:

  • 现场恢复

  • 初筛

  • 规律性排查

  • 证据提取

  • 报告整理

这些工作都非常适合 AI。

所以未来最先被替代的,不是“最难的专家判断”,而是:

中低复杂度 case 的标准化处理流程。

4.2 它可以把资深工程师的套路规模化复制

以前团队里的“高手”有一个很大的价值,是他知道:

  • 先查什么

  • 什么时候别查

  • 哪些输出是噪音

  • 哪些线索最值得追

而 AI + skills 做的事,就是把这些经验变成一个可复用模板。

一旦模板化成功,团队就不必每次都依赖同一个高手来完成首轮分析。

这会改变团队的人力结构。

4.3 它让“分析速度”和“报告表达能力”大幅提升

一个工程师再熟练,也有这些自然限制:

  • 会累

  • 会跳步骤

  • 会忘记记录

  • 会写报告写得很慢

  • 会在简单 case 上浪费很多时间

AI 则刚好擅长:

  • 不知疲倦地执行流程

  • 按规则保持结构化

  • 快速整理大量文本

  • 生成标准化报告

所以,AI 对稳定性工程师最大的冲击,不是“有没有比你聪明”,而是:

它在大量标准化环节上,比人更稳定、更快、更便宜。

五、那我们离“失业”还有多久?

如果问题是:

内核稳定性工程师会不会整体消失?

我的答案是:短期不会。

如果问题是:

现在这种工具是否已经开始侵蚀稳定性工程师原有的工作内容?

我的答案是:已经开始了。

不会立刻失业的原因

因为真正高质量的稳定性分析,仍然依赖这些能力:

  • 对平台架构的理解

  • 对硬件/内核/驱动/中间件边界的判断

  • 对异常上下文的真实语义理解

  • 对“假线索”和“真证据”的识别

  • 对业务影响和修复优先级的判断

  • 对工程系统约束的理解

AI 可以帮你分析,但它还不真正拥有“对系统全貌负责”的能力。

但重复型稳定性岗位一定会被压缩

如果一个岗位的主要价值是:

  • 会用 crash

  • 会查栈

  • 会导出日志

  • 会写基础报告

那么这种岗位风险已经非常高了。

因为这些能力正在被工具产品化。

未来最先被挤压的,很可能是:

  • 初级问题定位岗

  • 以 dump 初筛为主的工作

  • 报告整理型岗位

  • 纯工具操作型岗位

被替代的不是“内核知识”,而是“低密度劳动”

真正的问题不是:

“AI 会不会懂内核?”

而是:

“AI 会不会把那些低密度、高重复、可标准化的工作先吃掉?”

答案显然是会。

所以,稳定性工程师真正的风险,不是技术栈老不老,而是:

你的工作内容里,有多少是别人可以抽象成流程和策略的。

六、AI 时代,稳定性工程师应该怎么发展?

这是最重要的一部分。

如果我们接受一个事实:

AI 会越来越多地承担分析过程中的标准化环节。

那么稳定性工程师就必须往“更难被抽象、更难被替代”的方向进化。

我觉得至少有六个方向。

6.1 必须从“工具使用者”进化成“分析策略设计者”

以前大家比的是:

  • 谁更熟 crash

  • 谁记得更多命令

  • 谁手快

以后这些都不再是核心竞争力。

真正重要的是:

  • 你能不能定义分析流程

  • 你能不能把经验抽象成规则

  • 你能不能知道什么该先查、什么不该查

  • 你能不能设计好 AI 的决策边界

换句话说,未来高手不是最会敲命令的人,而是最会设计 investigation playbook 的人。

6.2 要具备把经验“结构化沉淀”的能力

很多资深工程师最大的问题是:

经验只在脑子里,不在系统里。

AI 时代,谁能把经验转成:

  • skill

  • prompt

  • 规则库

  • case template

  • 知识库

  • JSON schema

  • 调查路径树

谁就能放大自己的价值。

未来工程师之间的差距,不只是“你会不会分析”,而是:

你能不能把你的分析能力变成团队资产。

6.3 要更懂系统边界,而不只是内核点知识

AI 越擅长局部分析,人越要擅长全局判断。

比如:

  • 这是内核问题,还是驱动误用?

  • 是调度路径问题,还是上层业务造成的压力场景?

  • 是单点 crash,还是系统性稳定性风险?

  • 是符号不匹配导致误判,还是现场真的指向那个模块?

  • 是需要修代码,还是需要改配置、改策略、改监控?

这些都是“系统边界判断”,也是 AI 最难完全替代的部分。

6.4 要学会和 AI 协作,而不是和 AI 对抗

未来不是“人 vs AI”,而是“会用 AI 的工程师 vs 不会用 AI 的工程师”。

真正高效的工程师会把 AI 当成:

  • 首轮分析助手

  • dump triage 工具

  • 报告整理器

  • 证据摘要器

  • playbook 执行器

  • 自动化分析代理

而自己重点做:

  • 定义目标

  • 校正方向

  • 判断风险

  • 审核结论

  • 发现 AI 没看到的边界条件

谁越早学会这种协作方式,谁越不容易被替代。

6.5 要具备工程化和产品化思维

以前很多稳定性团队的问题是:

  • 分析能力很强

  • 但工具能力很弱

  • 很多经验重复劳动化

  • 很多方法依赖个人英雄主义

AI 时代会逼着稳定性工程师往前走一步:

不只是分析问题,还要思考怎么把分析流程产品化。

比如你要会想:

  • 这个过程能不能做成 MCP tool?

  • 哪些部分应该做成 skill?

  • 哪些输出应该结构化成 JSON?

  • 哪些命令应该自动裁剪?

  • 哪些 case 应该形成模板?

这已经不是纯故障分析能力,而是“分析系统设计能力”。

6.6 要加强表达、归因和决策能力

越往后,真正有价值的不是“跑出了多少命令”,而是:

  • 你能不能讲清楚根因

  • 你能不能说明证据强弱

  • 你能不能判断风险优先级

  • 你能不能给出正确的处置建议

AI 可以帮你写报告,但真正决定“报告是否可信、是否有用”的,仍然是人的判断框架。

所以稳定性工程师未来反而更需要:

  • 强表达

  • 强归因

  • 强决策

  • 强跨团队沟通

七、最后的启示:

不要问“会不会失业”,要问“你会变成什么样的工程师”

“我们离失业还有多久”这个标题,本质上不是在问一个时间点,而是在问一种方向感。

AI 时代,稳定性工程师真正的分化,大概会变成三类人:

第一类,纯工具操作型

他们会越来越危险,因为大量工作会被自动化。

第二类,资深分析型但经验不外化

他们短期仍然有价值,但影响力会局限在个人。

第三类,能把分析经验、工具能力、AI 协作、系统思维结合起来的人

这类人不会被削弱,反而会被放大。

因为未来真正稀缺的,不是会执行命令的人,而是能定义“怎么让 AI 正确分析问题”的人。

所以,与其问:

AI 还要多久让我失业?

不如问:

我还要多久,才能从“会分析问题的人”,变成“会设计分析系统的人”?

这可能才是 AI 时代内核稳定性工程师最重要的转型方向。

八、结语

我们现在这套工具,其实只是一个开始。

它已经证明了一件事:

  • AI 可以接入 crash

  • 可以恢复 split ramdump 现场

  • 可以根据输出选择下一条命令

  • 可以控制输出体积

  • 可以逐步逼近根因

  • 可以生成结构化报告

这并不意味着稳定性工程师要消失。

但它意味着,过去那种主要依赖人工重复劳动的分析模式,正在被快速淘汰。

未来最有价值的稳定性工程师,可能不再只是“最会查 dump 的人”,而是:

  • 最懂系统的人

  • 最会定义分析流程的人

  • 最会把经验沉淀成团队资产的人

  • 最会和 AI 协同工作的人

如果我们能顺着这个方向成长,那么 AI 不是失业倒计时,而是能力放大器。

如果我们拒绝变化,那么它迟早会变成替代者。

问题从来不是 AI 来不来。

问题是,当它真的开始接手分析时,我们是否已经准备好成为下一个阶段的工程师。


共勉!

刘琦

2026/03/11

附上一些截图以及演示视频

分析过程:

输出报告:

演示视频