做嵌入式 Linux 启动调试时,很多人最怕的不是“没日志”,而是日志很多,但看不懂重点。
串口上经常会刷出这些词:
• Kernel panic
• Oops
• VFS: Cannot open root device
• watchdog: watchdog0
看起来都像“系统挂了”,但它们其实不是一回事。
有的是结果,有的是过程,有的是根文件系统问题,有的是系统卡死后的复位现象。
这篇就按现场最常用的方式,把这 4 个高频关键词一次讲清。
看完至少能解决一个问题:
启动失败时,先知道自己该往哪一层排。
一、先记住一句话
这 4 个词可以先这样理解:
• panic:内核认为自己已经没法继续跑了
• oops:内核出错了,但不一定立刻死机
• VFS:根文件系统挂载链路出了问题
• watchdog:系统长时间没喂狗,被硬件或软件复位了
如果再压缩成一句更适合现场的口诀:
oops 是“出错”,panic 是“宣布撑不住了”,VFS 多半是根文件系统问题,watchdog 多半是系统卡住后的结果。
二、panic 到底是什么意思?
panic 最常见的完整日志通常像这样:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,2)
或者:
Kernel panic - not syncing: Attempted to kill init!
它的本质不是“一个具体模块名”,而是内核最后的终止态。
也就是说,panic 不是根因,往往只是结果。
内核遇到致命错误,判断已经不能安全继续运行,就会主动停下来。
常见触发场景
• 根文件系统挂不上
• init 进程启动失败
• 严重页错误或非法访问
• 某些 oops 升级成 panic
• 配置了 panic_on_oops
现场怎么理解
看到 panic,不要只盯着这一行。
真正有价值的,通常是它前面几行:
• 是不是先出现了 VFS
• 是不是先出现了 Unable to mount root fs
• 是不是先出现了 Attempted to kill init
• 是不是先出现了调用栈、异常地址、寄存器信息
结论:panic 往往是“最终判决”,不是第一现场。
三、oops 是什么?为什么它和 panic 不一样?
很多人第一次看到 Oops,会以为它和 panic 是同义词。
其实不是。
oops 更像是:
内核发生了一次严重异常,但还没到立刻全盘停机的程度。
常见日志会带这些字样:
Unable to handle kernel NULL pointer dereferenceInternal error: Oops: 96000004Oops: 0000 [#1] PREEMPT SMPPC is at xxxLR is at xxx
这通常意味着:
• 内核访问了非法地址
• 驱动里空指针解引用了
• 某个内核模块把内存踩坏了
• 当前上下文已经异常
oops 和 panic 的区别
最直白的理解就是:
• oops:内核出事了
• panic:内核宣布彻底跑不下去了
有些 oops 出现后,系统还能继续跑一会。
有些 oops 会因为异常太严重,或者配置原因,马上演变成 panic。
现场最常见的根因
• 驱动 probe 阶段空指针
• 时钟、GPIO、regmap、device tree 资源没拿到却直接用
• 中断处理函数访问了无效对象
• 释放后的内存再次访问
现场判断重点
看到 oops,第一优先级不是根文件系统,而是:
• 哪个函数崩了
• PC 在哪
• LR 在哪
• 调用栈最后落到哪个驱动
一句话:oops 更像代码问题,VFS 更像启动配置问题。
四、VFS 为什么在启动失败里这么高频?
VFS 是 Virtual File System,中文一般叫虚拟文件系统层。
在启动阶段,你最常见到的不是它的抽象概念,而是这句:
VFS: Cannot open root device "mmcblk0p2" or unknown-block(0,0)
或者:
VFS: Unable to mount root fs on unknown-block(179,2)
这类问题几乎可以直接理解成:
内核已经跑起来了,但根文件系统没挂上。
注意这点很关键。
出现 VFS,往往说明:
• CPU 已经进内核了
• 内核镜像大概率是起来了
• 串口、early boot 至少部分正常
真正挂掉的是rootfs 挂载链路。
最常见原因
• bootargs 里的 root= 写错
• SD 和 eMMC 设备号搞反了
• 分区号写错,比如 p2 写成 p1
• 忘了加 rootwait
• 文件系统驱动没编进内核
• MMC/SATA/NVMe 驱动没起来
• 设备树导致存储控制器没工作
典型误区
很多人看到 panic 就开始怀疑内核镜像。
但如果 panic 前面跟着 VFS,那重点通常不是镜像格式,而是:
• 根设备有没有枚举出来
• root= 对不对
• 驱动和设备树对不对
现场最快排查顺序
1. 看 bootargs 里的 root=
2. 看有没有 rootwait
3. 看块设备驱动是否编进内核
4. 看启动日志里 MMC/eMMC/NVMe 有没有正常枚举
5. 看设备树里存储控制器是否工作
一句话:VFS 不等于“内核没起来”,而是“内核起来了,但家没找到”。
五、watchdog 为什么总像“随机重启”?
watchdog 直译就是看门狗。
它的设计目的不是报错,而是防止系统卡死后永远挂住。
所以现场经常看到的现象是:
• 启动到一半突然重启
• 日志停在某处,然后板子自动复位
• 串口最后几行出现 watchdog 相关提示
比如:
watchdog: watchdog0: watchdog did not stop!
或者系统根本没来得及打印完整日志,就直接被复位。
它通常意味着什么?
在启动阶段看到 watchdog,很多时候并不是“watchdog 本身坏了”,而是:
系统在前面某处已经卡住了,后面没人喂狗,所以被复位了。
也就是说,watchdog 也常常不是根因,而是结果。
常见场景
• 驱动初始化死循环
• 某个硬件访问卡死
• 内核早期阶段中断/时钟异常
• 根文件系统切换后用户空间没起来,喂狗线程没启动
• panic 后系统停住,随后 watchdog 触发复位
现场怎么判断
如果板子总是“固定几秒后自动重启”,要高度怀疑 watchdog。
这时重点不是只看最后一行,而是找:
• 重启前最后正常打印到哪里
• 每次是不是都停在同一个位置
• 是进入内核后卡住,还是 userspace 前卡住
• 是不是先有 oops / panic,后有 watchdog
一句话:watchdog 常常说明系统先卡死了,复位只是后果。
六、这 4 个词该怎么区分?
可以直接记这张“现场脑图”:
看到 oops
先怀疑:驱动代码、空指针、非法访问
看到 panic
先问自己:前面那几行真正报了什么
看到 VFS
先怀疑:root=、存储驱动、分区、设备树、rootfs
看到 watchdog
先怀疑:系统前面卡死了,只是最后被复位
如果一定要排优先级,我建议这样:
1. 先找第一处异常
2. 不要只看最后一行
3. 先区分是代码崩、挂根失败、还是卡死复位
4. 再决定看驱动、bootargs、还是硬件链路
七、启动失败时最实用的判断法
现场不要一上来就大面积改配置,先按这四步走:
第一步:看最后一个关键词是什么
是 oops、panic、VFS 还是 watchdog。
第二步:往前翻 10 到 30 行
真正的根因通常在前面,不在最后一行。
第三步:先判断层次
• oops:代码异常
• VFS:根文件系统
• watchdog:卡死复位
• panic:最终终止态
第四步:再做最小化验证
• 改 root= 看 VFS 是否消失
• 关掉可疑驱动看 oops 是否消失
• 延长或关闭 watchdog 看是否能抓到更多日志
• 打开更早期日志,如 earlycon
八、最后记住这句
oops 看代码,VFS 看根文件系统,watchdog 看卡死复位,panic 看它前面那几行。