dev_info, dev_dbg Linux 内核动态调试

本文详细阐述了在Linux kernel驱动开发中,如何避免直接使用printk,转而采用dev_info、dev_dbg和dev_err进行模块信息和错误级别控制。介绍了动态调试的开启方法、控制dev_dbg输出的技巧,并解释了其工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目前在 kernel 驱动代码中,都不再建议直接使用printk直接添加打印信息,而是使用dev_infodev_dbgdev_err之类的函数代替,虽然这些dev_xxx函数的本质还是使用printk打印的,但是相比起printk

  • 支持打印模块信息、dev 信息
  • 支持动态调试 (dynamic debug) 方式

下面简述下这几个dev_xxx函数的基本使用规则,以及动态调试使用方式。

  • dev_info(): 启动过程、或者模块加载过程等 “通知类的” 信息等,一般只会通知一次,例如 probe 函数;
  • dev_dbg(): 一般使用在普通错误,如-EINVAL、-ENOMEM 等 errno 发生处,用于调试;
  • dev_err(): 一般使用在严重错误,尤其是用户无法得到 errno 的地方,或者程序员不容易猜测系统哪里出了问题的地方;

动态调试使用方法

  • 打开内核动态调试开关,make menuconfig选中CONFIG_DYNAMIC_DEBUG以及CONFIG_DEBUG_FS
  • Linux 启动后,使用命令行挂载上 dbgfs
mkdir /mnt/dbg
mount -t debugfs none /mnt/dbg
  • 使用下面方式控制你想输出 dev_dbg() 信息
    • 控制某个文件所有 dev_dbg(),echo -n "file xxx.c +p" > /mnt/dbg/dynamic_debug/control
    • 控制某个函数所有 dev_dbg(),echo -n "func xxx +p" > /mnt/dbg/dynamic_debug/control
  • 运行程序,使用 dmesg 则可以看到相应 dev_dbg() 的输出信息
  • 当调试结束,不再想输出 dev_dbg() 信息了,使用下面命令关闭即可
    • echo -n "file xxx.c -p" > /mnt/dbg/dynamic_debug/control
    • echo -n "func xxx -p" > /mnt/dbg/dynamic_debug/control

例子

  • echo -n "file ca_dsc_core.c +p" > /mnt/dbg/dynamic_debug/control 则打印ca_dsc_core.c所有的 dev_dbg() 信息
  • echo -n "func ca_dsc_read +p" > /mnt/dbg/dynamic_debug/control 则打印ca_dsc_read()函数所有 dev_dbg() 信息

动态打印调试的基本原理

当编译选项CONFIG_DYNAMIC_DEBUG打开的时候,在编译阶段,kernel 会把所有使用 dev_dbg() 的信息记录在一个 table 中,这些信息我们可以从/mnt/dbg/dynamic_debug/control解析出来:

# cat /mnt/dbg/dynamic_debug/control
... ...
... ...
drivers/alidrivers/modules/alidsc/ca_dsc_core.c:800 [alidsc]ca_dsc_probe_dt =_ "get dev-index error
<think>我们正在讨论Linux内核驱动中的动态调试(dynamic debugging)功能。用户询问如何在Linux驱动中启用dev_info功能。 注意:dev_info是一个宏,用于在驱动中打印设备信息。默认情况下,这些消息可能不会全部显示在控制台上,因为内核有日志级别设置。 但是,用户可能想了解如何控制这些消息的打印,包括如何启用/禁用它们。这通常通过动态调试(dynamic debugging)或内核配置实现。 根据引用[1]:pr_debug、dev_dbg动态调试。其中,对于命令`echo -n "file demo.c +p" > /sys/kernel/debug/dynamic_debug/control`,函数调用为:ddebug_proc_open ---> ddebug_proc_write [^1]。 这提示我们,动态调试机制可以控制pr_debug、dev_dbg等函数的输出。但是,用户问的是dev_info。 注意:dev_info通常使用dev_printk_emit(日志级别为KERN_INFO)打印消息,这些消息默认是启用的,会输出到控制台或日志文件(取决于系统配置)。但是,如果内核配置了动态调试,并且我们想对dev_info进行更细粒度的控制,可能需要考虑其他方法。 然而,实际上,dev_info消息通常总是被打印(只要日志级别允许,因为KERN_INFO的级别是6,而控制台默认级别是7,所以通常都会显示)。所以用户的问题可能是如何控制这些信息(比如在不需要的时候不打印)? 但用户明确说“启用”,所以可能是他们目前没有看到dev_info的输出?这可能有以下原因: 1. 内核日志级别设置过高,导致低于该级别的信息不显示。可以通过`dmesg -n 8`(设置控制台日志级别为8,即显示所有消息)来确保显示所有消息。 2. 驱动中的dev_info被条件编译关闭了?例如,使用#ifdef DEBUG等。 不过,在标准的驱动中,dev_info通常不会被条件编译关闭。所以更可能是日志级别的问题。 另外,动态调试(dynamic_debug)通常用于控制dev_dbg(以及pr_debug、print_hex_dump_debug等)的输出,而不是dev_info。因此,对于dev_info,我们通常不能像动态调试那样在运行时动态开关。 但是,我们可以通过以下方式控制内核消息的输出: - 调整控制台日志级别:通过`dmesg -n level`(level是一个从0到8的整数,8表示显示所有消息,0表示只显示紧急消息)或者修改/proc/sys/kernel/printk。 - 使用动态调试来控制dev_dbg:如果用户希望将一些信息消息改为使用dev_dbg打印,那么就可以利用动态调试在运行时启用或禁用。 如果用户确实想控制dev_info的输出,可能需要修改代码,将dev_info改为dev_dbg,然后使用动态调试来控制。 步骤: 1. 在驱动中,将需要动态控制的消息从dev_info改为dev_dbg。 2. 编译驱动时,确保定义了CONFIG_DYNAMIC_DEBUG(通常在现代内核中都是启用的)。 3. 在运行时,使用动态调试控制: 启用:`echo -n 'file <filename> +p' > /sys/kernel/debug/dynamic_debug/control` 禁用:`echo -n 'file <filename> -p' > /sys/kernel/debug/dynamic_debug/control` 注意:<filename>是包含dev_dbg调用的源文件名。 引用[1]中提到的命令就是用于动态调试的。 另外,引用[2]和[3]是关于USB设备驱动匹配的,与当前问题关系不大,因此我们主要参考引用[1]。 因此,回答用户: 1. 解释dev_info默认是启用的,但可能因为日志级别而看不到。 2. 如果希望动态控制,建议将信息改为dev_dbg,然后使用动态调试机制。 同时,生成相关问题。</think>### 如何在 Linux 驱动中启用 `dev_info` 功能 在 Linux 驱动开发中,`dev_info` 是设备信息打印的标准宏(定义于 `<linux/dev_printk.h>`),**默认处于启用状态**,无需特殊配置。其行为由以下因素控制: #### 1. **基本使用方式** 直接调用宏即可输出设备信息: ```c dev_info(&pdev->dev, "设备初始化成功,寄存器基址:0x%lx\n", reg_base); ``` - **输出位置**:内核日志缓冲区(通过 `dmesg` 查看) - **日志级别**:`KERN_INFO`(优先级 6),默认会被系统记录 --- #### 2. **控制输出可见性** 若未看到输出,需检查以下配置: - **内核日志级别** 通过 `/proc/sys/kernel/printk` 控制输出阈值: ```bash # 确保控制台日志级别允许 INFO 输出(默认值通常为 7) echo 8 > /proc/sys/kernel/printk # 启用所有级别日志 ``` - **系统日志服务** 检查 `rsyslog`/`journald` 是否过滤了内核日志。 --- #### 3. **动态调试进阶控制(替代方案)** 若需运行时动态开关消息,建议改用 `dev_dbg`: ```c // 驱动代码中 dev_dbg(&dev->pdev, "调试信息:当前状态=%d", state); ``` **启用步骤**: 1. 确保内核配置开启 `CONFIG_DYNAMIC_DEBUG=y` 2. 运行时激活调试: ```bash # 启用特定文件的 dev_dbg 输出 echo -n "file driver_core.c +p" > /sys/kernel/debug/dynamic_debug/control ``` `+p` 表示启用打印(`-p` 禁用),该机制通过修改函数指针实现动态控制[^1]。 --- #### 4. **设备匹配与日志关联** 当驱动与设备匹配时(如 USB 设备通过 `struct usb_device_id` 匹配[^2]),`dev_info` 常用于记录匹配成功事件: ```c static int my_probe(struct usb_interface *intf, const struct usb_device_id *id) { dev_info(&intf->dev, "设备匹配成功,ID=%04X:%04X\n", id->idVendor, id->idProduct); ... } ``` 匹配流程由总线层(如 `pci_bus_match`[^3])触发,无需额外日志启用操作。 --- ### 常见问题排查 | 现象 | 解决方案 | |---------------------|----------------------------------| | 无任何输出 | 检查日志级别、驱动是否成功加载 | | 仅缺 `dev_info` | 确认代码执行路径是否到达 | | 需动态开关 | 改用 `dev_dbg` + 动态调试机制 | > **关键总结**:`dev_info` 设计为"始终启用",若需精细控制请使用动态调试机制操作 `dev_dbg`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码撸起

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值