🚀
在 Linux 驱动开发过程中,调试信息的输出是我们定位问题、理解内核执行流程的第一武器。而与 printk()
并列,内核为我们提供了一个更具语义化和上下文感知能力的日志接口:dev_info()
。本文将围绕 dev_info()
展开,讲清它的使用方式、适用场景、输出机制以及与其他调试手段的比较,帮助你在实际调试中更加得心应手。
📌 为什么需要 dev_info()
?
传统的 printk()
当然能用,但它存在两个问题:
- 输出不带上下文:你无法直接知道哪一个设备、哪一条总线产生了这条日志。
- 维护性差:在多设备、多模块并存的复杂系统中,
printk()
的信息常常缺乏“来源说明”。
而 dev_info()
提供了解决方案:
- 自动输出设备名称、驱动名、总线名
- 日志更具结构性,便于筛选与追踪
- 与设备生命周期绑定,语义更明确
🔍 dev_info()
是什么?
dev_info()
是 Linux 内核中的一个宏定义,声明在:
#include <linux/device.h>
用于输出级别为 KERN_INFO
的日志,绑定在特定 struct device *
对象上。与它一同提供的还有:
函数名 | 含义 | 输出级别 |
---|---|---|
dev_emerg() | 紧急错误(系统崩溃) | KERN_EMERG |
dev_alert() | 严重警告 | KERN_ALERT |
dev_crit() | 关键错误 | KERN_CRIT |
dev_err() | 一般错误 | KERN_ERR |
dev_warn() | 警告 | KERN_WARNING |
dev_info() | 一般信息 | KERN_INFO |
dev_dbg() | 调试信息(需打开) | KERN_DEBUG |
🧩 dev_info()
实战示例
以 I2C 设备驱动为例,在 probe()
函数中添加日志输出:
static int my_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
dev_info(&client->dev, "my_i2c_driver: probe called\n");
// ...初始化代码...
return 0;
}
启动内核后,在 dmesg
中你可以看到:
[ 3.452184] my_i2c_driver 1-0050: my_i2c_driver: probe called
这条日志不仅包含了你写入的信息,还附带了设备名(如 1-0050
表示 i2c-1 总线上的 0x50 地址设备)。
🔧 输出日志在哪看?
你可以通过以下方式查看:
dmesg | grep my_i2c_driver
或者查看串口输出(如使用 minicom
)的内核启动日志。
🧠 dev_info()
背后的工作机制
dev_info()
的本质是封装了 printk()
,但它调用了 dev_printk()
,能自动从 struct device
中获取信息进行格式化输出:
dev_printk(KERN_INFO, dev, fmt, ...);
输出内容类似:
[时间戳] 设备名:消息内容
这让你的日志天然带有设备来源信息,尤其适合多实例设备(如多个 I2C 设备)共用驱动的场景。
🛠️ dev_dbg()
与动态调试
有些人会问:为什么我用 dev_dbg()
打印不出来?
这是因为 dev_dbg()
的默认行为是 关闭的。你需要手动打开 dynamic debug:
开启 dynamic debug(示例)
echo 'file drivers/i2c/* +p' > /sys/kernel/debug/dynamic_debug/control
或者在模块中启用:
#define DEBUG
#include <linux/device.h>
如果你不想控制开关,建议统一使用 dev_info()
。
📘 dev_info()
与 printk()
的对比
维度 | dev_info() | printk() |
---|---|---|
是否绑定设备上下文 | ✅ 是 | ❌ 否 |
输出是否包含设备信息 | ✅ 是 | ❌ 否 |
适合用于模块化驱动 | ✅ 非常适合 | ❌ 不适合大型驱动 |
用法灵活性 | 中(需传 dev ) | 高(直接调用) |
📦 推荐使用时机
场景 | 推荐使用 |
---|---|
probe() 入口/出口调试 | ✅ dev_info() |
获取资源失败(regmap/clk) | ✅ dev_err() |
中断触发验证 | ✅ dev_info() 或 dev_dbg() |
配置状态检查(如 suspend/resume) | ✅ dev_info() |
✅ 总结
dev_info()
是 Linux 驱动开发中推荐使用的日志打印方式。相较于传统的 printk()
,它更具结构化、语义清晰、上下文感知能力。通过与 struct device
绑定,它可以让你在驱动调试中更加有针对性地观察设备行为,尤其适用于复杂 SoC、BSP、I2C/SPI 平台等多设备场景。
建议你在今后的驱动开发中,将 dev_info()
、dev_err()
、dev_dbg()
等用法作为调试日志的默认选择,全面提升代码质量与可维护性。
📌 你是否正在调试某个驱动匹配不成功的问题?不妨马上在 probe()
中加上 dev_info()
看看吧!
如需配套代码模板、调试脚本或 DTS 示例,欢迎关注我的平台“嵌入式Jerry”,每日一练,一起进阶。
📺 视频教程请关注 B 站:“嵌入式 Jerry”