3、dmesg 高级用法:参数实战与日志过滤
在 RK3568 显示驱动调试中,基础 dmesg 命令往往输出海量信息,直接阅读效率极低。本章聚焦 dmesg 的高级参数组合与文本过滤工具(grep/awk/sed)的实战配合,帮助开发者从杂乱日志中快速定位 DRM/KMS、MIPI DSI、HDMI 等显示子系统的关键事件与错误。
3.1 核心参数实战:-c / -w / -l / -t / -x
以下参数是日常调试中使用频率最高的组合,每个参数解决一类特定场景。
| 参数 | 功能 | 典型调试场景 |
|---|---|---|
-c |
读取并清除内核环形缓冲区 | 在驱动加载前后分别执行,只保留新产生的日志 |
-w |
实时等待新日志(类似 tail -f) | 监控热插拔、中断、时序切换时的即时输出 |
-l |
按日志级别过滤(err/warn/info/debug) | 只查看错误或警告,排除冗余 info 信息 |
-t |
不打印时间戳 | 减少行宽,便于复制关键错误码 |
-x |
显示日志级别与 facility 的原始编码 | 确认某条日志的优先级是否被用户态错误修改 |
实战建议:在 RK3568 开发板上加载显示驱动前,先执行
dmesg -c 清空缓冲区;加载后执行 dmesg -l err 只查看错误级日志,避免被大量 probe 信息淹没。
3.1.1 参数组合示例
# 清空缓冲区后,实时监控错误级日志(最常用组合)
dmesg -c && dmesg -w -l err
# 只查看最近 50 条与 DRM 相关的日志,不显示时间戳
dmesg -t | grep -i drm | tail -50
# 查看所有日志级别编码,确认某条日志的原始优先级
dmesg -x | grep "rockchip-drm"
技巧:使用
-x 参数时,输出格式为 <facility>.<level>,例如 <6> 表示内核信息(KERN_INFO),<3> 表示错误(KERN_ERR)。在显示驱动调试中,若看到本应为 error 的日志却显示为 <6>,说明驱动中 printk 级别使用错误。
3.2 日志过滤三剑客:grep / awk / sed
单独使用 dmesg 参数仍不足以应对复杂场景,必须结合文本处理工具进行二次过滤。以下是在 RK3568 显示驱动调试中的典型用法。
3.2.1 grep:关键词快速定位
# 查找所有与显示子系统相关的日志(不区分大小写)
dmesg | grep -iE "drm|hdmi|dsi|edp|lvds|vop"
# 显示匹配行及其前后各 3 行上下文(定位错误来源)
dmesg | grep -i -B3 -A3 "rockchip-drm.*fail"
# 反向过滤:排除时间戳和 CPU 调频等无关信息
dmesg | grep -vE "cpufreq|thermal|devfreq"
3.2.2 awk:结构化字段提取
当需要从日志中提取时间戳、函数名、错误码等结构化字段时,awk 是最佳选择。
# 提取所有包含 "irq" 的日志,只显示第 1 列(时间戳)和第 5 列(函数名)
dmesg | grep "irq" | awk '{print $1, $5}'
# 统计每种日志级别的出现次数
dmesg | awk '{print $4}' | sort | uniq -c | sort -rn
# 提取 DRM 子系统中所有包含数字错误码的行
dmesg | grep -i "drm" | awk '{for(i=1;i<=NF;i++) if($i ~ /-[0-9]+/) print $i}'
3.2.3 sed:日志文本清洗与格式化
# 删除所有时间戳,只保留日志正文
dmesg | sed 's/^\[.*\] //'
# 将日志中的 "rockchip-drm" 缩写为 "RKD"(减少行宽)
dmesg | sed 's/rockchip-drm/RKD/g'
# 只保留包含 "dsi" 或 "hdmi" 的行,并删除空行
dmesg | grep -iE "dsi|hdmi" | sed '/^$/d'
注意:在 RK3568 平台上,显示驱动的 probe 顺序可能影响日志输出。使用
dmesg | grep -i "drm" | awk '{print $1, $0}' 可以按时间戳排序,确认 VOP、HDMI、DSI 的初始化先后关系。
3.3 显示驱动专用过滤模式
针对 RK3568 显示子系统的常见模块,以下过滤模板可直接用于调试。
| 过滤目标 | 过滤命令 | 关注点 |
|---|---|---|
| DRM 核心 | dmesg | grep -i "drm\|drm_kms_helper" |
probe 成功/失败、connector 状态、fb 创建 |
| VOP 显示控制器 | dmesg | grep -i "vop\|vop2" |
时钟使能、中断注册、图层配置 |
| MIPI DSI | dmesg | grep -i "dsi\|mipi" |
PHY 初始化、时序参数、LP/HS 模式切换 |
| HDMI | dmesg | grep -i "hdmi\|dw-hdmi" |
EDID 读取、HDCP 认证、音频时钟 |
| eDP/LVDS | dmesg | grep -i "edp\|lvds\|panel" |
背光控制、链路训练、面板时序 |
3.4 日志过滤流程架构
以下 SVG 图展示了从原始 dmesg 输出到最终调试结论的完整过滤链路。
3.5 实战案例:定位 RK3568 HDMI 无显示问题
以下是一个完整的调试会话,展示如何组合使用上述工具。
# 步骤1:清空旧日志,加载驱动
dmesg -c
modprobe rockchipdrm
# 步骤2:实时监控错误,同时保存完整日志
dmesg -w -l err &
dmesg > /tmp/full_drm.log
# 步骤3:过滤 HDMI 相关错误
dmesg | grep -i "hdmi" | grep -i "fail\|error\|timeout"
# 步骤4:提取 EDID 读取状态
dmesg | grep -i "edid" | awk '{print $1, $NF}'
# 步骤5:查看中断注册情况
dmesg | grep -i "irq" | grep -i "hdmi\|dw-hdmi"
经验总结:在 RK3568 平台上,HDMI 无显示最常见的原因是 EDID 读取超时或 PHY 初始化失败。使用
dmesg | grep -i "edid" | awk '{print $1, $0}' 可以快速确认 EDID 是否在预期时间点被成功读取。
3.6 日志过滤效率对比
| 方法 | 适用场景 | 效率 | 学习成本 |
|---|---|---|---|
| dmesg 原生参数 | 快速查看错误/警告 | 高 | 低 |
| grep 关键词过滤 | 按模块/关键字搜索 | 高 | 低 |
| awk 字段提取 | 结构化数据统计 | 中 | 中 |
| sed 文本清洗 | 日志格式化/缩写 | 中 | 中 |
| 组合管道 | 复杂调试场景 | 极高 | 较高 |
核心原则:在 RK3568 显示驱动调试中,优先使用
dmesg -l err -w 实时监控,再通过 grep -i 按模块缩小范围,最后用 awk 提取关键字段。避免一次性使用过于复杂的管道链,应逐步迭代过滤条件。