内核调试打印命令

用来开启内核启动 / 驱动加载 / 电源管理的详细调试日志,专门用于排查启动慢、驱动卡死、初始化时序、probe 耗时问题。


1. echo 1 > /sys/power/pm_print_times

作用

开启【电源管理(PM)操作耗时打印】

输出日志效果

内核会打印:

复制代码
PM: suspend exit took 23.456 ms
PM: resume device took 10.123 ms

用途

睡眠 / 唤醒 / 设备挂起 / 恢复花了多少时间。


2. echo 1 > /sys/power/pm_debug_messages

作用

开启【电源管理完整调试日志】

输出日志效果

会打印每个设备 suspend/resume 的详细过程:

复制代码
PM: suspend device: mmc0
PM: resume device: qspi

用途

排查休眠唤醒卡住、驱动不工作。


3. echo N > /sys/module/printk/parameters/console_suspend

作用

禁止控制台在 suspend 时关闭

效果

系统休眠 / 唤醒时,串口 / 控制台日志不会中断,能完整看到 PM 过程。

关键

默认 Y → 休眠时关闭控制台,日志会丢。设为 N调试必备


4. echo Y > /sys/module/kernel/parameters/initcall_debug

✅ 这就是你截图里日志的真正来源!!!

作用

开启【内核初始化函数调用调试】

输出日志(你截图里的内容)

复制代码
calling xxx_probe @ 60
xxx_probe returned 0 after 123 usecs

解释

  • @ 60 = 进程 PID 1(init 进程)
  • 打印每个驱动、子系统、模块的初始化顺序和耗时

用途

  1. 看驱动加载顺序
  2. 看哪个 probe 函数慢 / 卡死
  3. 看启动流程调用关系

5. echo 8 > /proc/sys/kernel/printk

作用

把控制台日志级别开到最大(8 = 显示所有等级)

日志级别说明

复制代码
0: EMERG
1: ALERT
2: CRIT
3: ERR
4: WARNING
5: NOTICE
6: INFO
7: DEBUG
8: 所有都打印

效果

所有调试信息、初始化信息、驱动信息都会输出。


6. echo 1 > /sys/module/printk/parameters/time

作用

给每一条内核日志前面加上时间戳

输出效果

复制代码
[ 12.345678 ] calling xxx_probe

用途

精确看哪一步耗时、哪一步卡住、启动时序


最终总结(一句话记住)

这 6 条命令组合起来 =

【全开内核最详细调试日志】

包含:

  1. initcall 初始化调用关系
  2. 驱动 probe 耗时
  3. 电源管理 suspend/resume 日志
  4. 控制台不中断
  5. 所有级别日志输出
  6. 带时间戳


一份完整可直接复制的 U-Boot bootargs 配置,开机就能默认开启你截图里那种调用关系日志,还会顺带把所有调试选项都配好,一步到位。


一、核心原理

这些调试参数有两种开启方式:

  1. 像你之前那样,在系统运行时用 echo 命令写入 /sys/...(只能控制后续日志)
  2. 在 U-Boot 里写入 bootargs(内核启动参数),从内核启动第一行就生效,这就是你截图里日志的来源方式。

二、直接可用的完整 bootargs 配置

你可以直接在 U-Boot 命令行里运行这几条,也可以写入 bootcmd 永久保存:

运行

复制代码
# 先查看当前 bootargs,避免覆盖掉原来的关键参数(比如 console、root 等)
printenv bootargs

# 开启所有调试日志的 bootargs(把你的原有参数拼接进去即可)
setenv bootargs "console=ttyS0,115200 earlycon root=/dev/mmcblk0p2 rw rootwait \
initcall_debug loglevel=8 printk.time=1 pm_print_times=1 pm_debug_messages=1 \
console_suspend=0"

# 保存环境变量(可选,重启后仍生效)
saveenv

# 启动内核
boot

三、每个参数的作用详解

我把你之前用的 6 条命令,都对应成了内核启动参数,一一对应说明:

内核启动参数 对应你之前的命令 作用
initcall_debug echo Y > /sys/module/kernel/parameters/initcall_debug 开启你截图里的核心功能:打印所有驱动 / 子系统初始化调用关系、probe 耗时,就是 calling xxx @ 60 日志的来源
loglevel=8 echo 8 > /proc/sys/kernel/printk 把日志级别开到最大,显示所有等级的内核日志(包括 debug 信息)
printk.time=1 echo 1 > /sys/module/printk/parameters/time 给每条日志加上时间戳,方便定位哪一步耗时 / 卡住
pm_print_times=1 echo 1 > /sys/power/pm_print_times 打印电源管理操作的耗时,排查休眠 / 唤醒问题
pm_debug_messages=1 echo 1 > /sys/power/pm_debug_messages 打印电源管理完整调试日志,包括每个设备的 suspend/resume 过程
console_suspend=0 echo N > /sys/module/printk/parameters/console_suspend 禁止控制台在休眠时关闭,确保 PM 过程的日志不会丢失

四、额外补充:永久生效的两种方式

方式 1:U-Boot 里直接保存(推荐)

刚才的 setenv bootargs + saveenv 就是这种方式,重启后依然有效,适合调试阶段快速开启。

方式 2:设备树 / 内核配置里永久开启(量产前建议用)

如果想直接编译进内核,不用每次都改 bootargs,可以修改内核配置:

复制代码
make menuconfig
# 路径:
Kernel hacking  --->
    [*]   Enable initcall debugging
    [*]   Support for dynamic printk() time stamps
Power management options  --->
    [*]   PM debug messages
    [*]   Print PM times
Console drivers  --->
    [ ]   Suspend console during suspend/resume

配置完成后重新编译内核,就不用再改 bootargs 了。


五、调试完之后怎么关掉?

调试结束后,不想再看到满屏日志,只需要:

复制代码
# U-Boot 里恢复原来的 bootargs
setenv bootargs "console=ttyS0,115200 earlycon root=/dev/mmcblk0p2 rw rootwait"
saveenv

或者直接把 initcall_debug loglevel=8 printk.time=1 pm_print_times=1 pm_debug_messages=1 console_suspend=0 这些参数删掉即可。


💡 小提示:开启这些日志后,启动速度会稍微变慢,因为内核要额外打印很多调试信息,属于正常现象,调试完成后建议关闭。

  1. debug_log_on.sh 全开调试(对应你那 6 条命令 + 内核调用耗时、时间戳、PM 调试)
  2. debug_log_off.sh 全关调试、恢复默认日志级别

一、一键开启调试脚本 debug_log_on.sh

复制代码
#!/bin/sh
# 开启内核全量调试日志、initcall 调用栈、PM调试、时间戳、控制台不挂起

echo 1 > /sys/power/pm_print_times
echo 1 > /sys/power/pm_debug_messages

echo N > /sys/module/printk/parameters/console_suspend
echo Y > /sys/module/kernel/parameters/initcall_debug

# 最大日志级别 8
echo 8 > /proc/sys/kernel/printk

# 日志打印时间戳
echo 1 > /sys/module/printk/parameters/time

echo "====================================="
echo "  内核调试日志 已全部开启"
echo "  生效内容:"
echo "  1. initcall_debug 驱动probe调用+耗时"
echo "  2. 全部等级printk打印(loglevel=8)"
echo "  3. 日志带时间戳"
echo "  4. 电源PM调试+耗时"
echo "  5. 休眠不关闭串口控制台"
echo "====================================="

二、一键关闭调试脚本 debug_log_off.sh

复制代码
#!/bin/sh
# 关闭所有额外调试,恢复系统默认日志输出

echo 0 > /sys/power/pm_print_times
echo 0 > /sys/power/pm_debug_messages

echo Y > /sys/module/printk/parameters/console_suspend
echo N > /sys/module/kernel/parameters/initcall_debug

# 恢复常规日志级别 4(警告+错误)
echo 4 4 1 7 > /proc/sys/kernel/printk

# 关闭日志时间戳
echo 0 > /sys/module/printk/parameters/time

echo "====================================="
echo "  内核调试日志 已关闭,恢复默认"
echo "====================================="

三、使用方法(嵌入式 Linux 直接能用)

  1. 新建文件、粘贴内容

    vi debug_log_on.sh
    vi debug_log_off.sh

  2. 加执行权限

    chmod +x debug_log_on.sh
    chmod +x debug_log_off.sh

  3. 执行开启

    ./debug_log_on.sh

  4. 调试完关闭

    ./debug_log_off.sh


四、补充关键说明

  1. 你开机看到的:calling xxx_probe @ xx / returned 0 after xxx usecs完全由 initcall_debug 控制,关了就彻底没有。

  2. printk 四字段含义(恢复默认那条):

    echo 4 4 1 7 > /proc/sys/kernel/printk

  • 控制台级别
  • 日志缓存级别
  • 最小阻塞级别
  • 默认日志级别
  1. 结合前面 U-Boot bootargs
  • 想要开机自启调试 → 用 bootargs 加参数
  • 想要运行时临时开关 → 用上面两个脚本