12、启动日志分析:Kernel Log、Logcat、Dmesg在启动过程中的应用、如何抓取启动日志。

做Android底层开发,说白了就是跟启动过程死磕。系统起不来、外设不工作、卡在开机动画——这些破事我几乎天天遇到。怎么定位?靠的就是日志。

今天咱们聊聊启动过程中的三把利器:Kernel LogLogcatDmesg。它们各自管什么、什么时候用、怎么抓,我一次性给你讲透。

这三者到底有什么区别?

先别急着上手敲命令。你得先搞清楚,这三个东西分别是谁的“日记本”。

日志类型 来源 覆盖阶段 典型内容
Kernel Log Linux 内核 从 Bootloader 交权后到系统完全启动 驱动加载、内存初始化、文件系统挂载
Dmesg 内核环形缓冲区 内核启动全程 + 运行时内核消息 硬件探测、中断分配、电源管理
Logcat Android 框架层 Zygote 启动后到系统完全就绪 ServiceManager、AMS、WMS 等系统服务日志

我个人的习惯是:先看 Kernel Log 确认硬件层没问题,再看 Logcat 排查上层服务。Dmesg 呢?它更像是 Kernel Log 的“完整版”,启动后也能用。

Kernel Log:启动早期的“黑匣子”

Kernel Log 记录的是内核从解压到初始化完成的全过程。你想想看,这时候 Android 还没起来,Logcat 根本不能用。所以它是启动早期唯一的救命稻草。

怎么抓?最靠谱的方式是通过 UART 串口。我在项目中遇到过一台设备,USB 口在启动初期根本没驱动,串口是唯一能拿到日志的通道。

# 通过串口工具抓取
screen /dev/ttyUSB0 115200

# 或者用 minicom
minicom -D /dev/ttyUSB0 -b 115200

如果你没有串口线,也可以试试在 Bootloader 阶段开启 console 输出。嗯,这里要注意:很多厂商的 Bootloader 默认关掉了串口输出,你得在编译时打开。

关键信息点:Kernel Log 里出现 [ OK ] 不代表万事大吉。我见过驱动报 probe failed 但系统仍然继续启动的情况。一定要逐行检查 errorfailwarning 关键字。

Dmesg:内核的“实时监控”

Dmesg 和 Kernel Log 其实是一回事,只不过 Dmesg 读取的是内核环形缓冲区。系统启动后,你随时可以用 dmesg 命令查看历史消息。

为什么需要它?因为有些内核消息一闪而过,你根本来不及在串口里看清。启动完成后执行 dmesg,所有内核消息都还在。

# 查看所有内核消息
dmesg

# 只看错误和警告
dmesg | grep -iE "error|fail|warn"

# 带时间戳查看
dmesg -T

# 实时监控内核消息
dmesg -w

我曾经遇到一个诡异的问题:设备偶尔启动到一半就死机。用 dmesg 对比正常启动和异常启动的日志,发现异常时 mmc0: timeout 出现了三次。最后定位到是 eMMC 供电时序问题。你看,没有 Dmesg 对比,这种偶发问题根本没法查。

小技巧:Dmesg 缓冲区大小有限。如果系统运行时间长了,早期的启动消息会被覆盖。建议启动后第一时间执行 dmesg > /data/kernel_boot.log 保存下来。

Logcat:Android 框架的“体检报告”

Logcat 是 Android 层最常用的日志工具。但它有个坑:在 Zygote 启动之前,Logcat 是空的。所以它只能覆盖启动的中后期。

什么时候用 Logcat?系统服务崩溃、开机动画卡住、Launcher 启动失败——这些场景 Logcat 是首选。

# 抓取所有日志
logcat -b all

# 只看系统服务相关
logcat -b system

# 带时间戳
logcat -v time

# 保存到文件
logcat -f /data/logcat_boot.log -v time

我个人习惯在 init.rc 里提前启动 logcat 服务,这样能抓到更早的日志:

# 在 init.rc 中添加
service boot_logger /system/bin/logcat -b all -f /data/boot.log -v time
    class core
    user root
    group root
    oneshot

这样做的好处是,即使系统启动到一半挂了,日志文件已经写进去了。重启后还能看到死机前的最后一刻发生了什么。

注意:Logcat 的缓冲区也是有限的。默认主缓冲区只有 256KB。如果启动过程中日志量很大,早期的日志会被覆盖。建议在开发阶段把缓冲区调大:logcat -G 2M

如何系统化抓取启动日志?

光知道单个工具还不够。你得有一套完整的抓取策略。我总结了一个“三段式”方法:

  1. Bootloader 阶段:通过 UART 串口抓取,或者开启 Bootloader 的 log 输出到内存特定地址。
  2. 内核阶段:通过 dmesg 或串口抓取 Kernel Log。建议同时开启 initcall_debug 内核参数,能看到每个驱动的初始化耗时。
  3. Android 阶段:通过 logcat -b all 抓取。如果怀疑是某个特定服务的问题,可以加 -s 过滤 TAG。

下面这张图能帮你理清思路:

启动日志抓取策略全景图 Bootloader Kernel Android Framework Bootloader 阶段 抓取方式:UART 串口 内核阶段 抓取方式:dmesg / 串口 Android 阶段 抓取方式:logcat 各阶段关键工具与命令 Bootloader • 串口工具:screen / minicom • 开启 console 输出 Kernel • dmesg -T(带时间戳) • dmesg | grep error • 内核参数:initcall_debug Android • logcat -b all • logcat -v time • init.rc 预启动 logcat 提示:建议启动后第一时间保存 dmesg 和 logcat 到文件,防止缓冲区被覆盖

实战:一次完整的启动日志抓取流程

假设你拿到一台新设备,启动卡在开机动画。你会怎么做?

我的流程是这样的:

  1. 接上串口线,设置波特率 115200,打开串口工具。
  2. 重启设备,观察串口输出。如果看到 Kernel panic - not syncing,那就是内核挂了,直接看 Kernel Log 定位。
  3. 如果串口没输出,检查 Bootloader 是否开启了 console。我遇到过一台设备,Bootloader 默认把串口当 GPIO 用了,得改 dts。
  4. 系统启动后,立即执行 dmesg > /data/dmesg.loglogcat -b all -f /data/logcat.log -v time
  5. 对比正常设备的日志,找出差异点。

避坑指南:我曾经在抓 Logcat 时发现日志里全是 Buffer overflow,以为是系统崩溃了。后来才发现是 Logcat 缓冲区太小,日志被截断了。所以第一步先调大缓冲区:logcat -G 4M

总结一下

Kernel Log 看硬件,Dmesg 看内核,Logcat 看框架。三者配合使用,才能覆盖启动全过程。

我个人建议你在开发阶段就把日志抓取流程自动化。写个脚本,启动后自动保存 dmesg 和 logcat 到 data 分区。这样出了问题,直接拿日志分析,不用再复现。

嗯,日志分析这事,说白了就是“对比”。正常日志和异常日志放一起,差异点就是问题所在。多练几次,你也能一眼看出问题在哪。


公众号:蓝海资料掘金营,微信deep3321