启用 Linux 内核驱动程序 dev_dbg 调试信息。

28

有没有一种最简单的方法启用linux内核驱动程序dev_dbg调试消息(实际上是trace类型的消息),而不需要涉及内核打补丁/重新编译或驱动程序实现类似于debugfs的额外内容?也许有一种方法可以在内核中启用某些简单的东西(比如一个标志?)触发特定驱动程序或所有驱动程序的dev_dbg(它可以通过`dmesg | grep“driverName”`来过滤输出)?

内核版本为4.14。根本没有运行syslog / daemonlog / system日志。没有网络接口,只有一个串口可用。目标系统非常缓慢并且非常紧凑,因此没有办法添加syslog / etc,除了dmesg之外什么都没有,在那里确切地可以看到像这样的行的输出:

dev_dbg(&client->dev, "bla bla bla\n");

一些帖子已经建议在bootargs内核参数中添加debug关键字,但不幸的是这并不足够。

dev_info这样的输出没有任何问题地进入dmesg,因此肯定是有点接近的。谢谢


https://www.kernel.org/doc/html/v4.11/dev-tools/gdb-kernel-debugging.html - Knud Larsen
6个回答

23

接收dev_dbg消息的最简单方法,不需要安装/配置syslog等,需要执行以下步骤:

  1. debug关键字提供到bootargs内核参数中

  2. 如果驱动程序是单个文件并且使用常见的Makefile,则将#define DEBUG追加到驱动程序文件的第一行,或者如果驱动程序由多个源文件组成并且通常有自己的Makefile,则在CC构建选项中添加-DDEBUG

  3. 在内核引导并出现提示后,通过执行dmesg -n 8echo 8 > /proc/sys/kernel/printk来启用调试级别消息

  4. 如果模块与命令集成,则使用insmod <driver name>modprobe <driver name>命令加载驱动程序,如果驱动程序已经存在于内核中,则插入命令可能会有所不同。

如何为总线子系统分配内核集成驱动程序的示例:

echo <driver name> <i2c bus address> > /sys/bus/i2c/devices/i2c-0/new_device

附注:

如果DTS具有驱动程序记录分配,手动重复的驱动程序分配将导致错误 - 在i2c子系统情况下 - 错误EBUSY(-16),驱动程序将在命令提示符之前被分配,并且dmesg消息将限制为默认级别(通常仅为dev_info)。
如果驱动程序已经由DTS分配,并且没有办法暂时从树源中排除它 - 在启用了调试(跟踪)级别消息后,将其分离并重新附加是有用的。
对于i2c子系统,需要执行以下命令:
echo > /sys/bus/i2c/drivers//unbind
然后
echo > /sys/bus/i2c/drivers//bind
警告:
内核驱动程序跟踪机制无法帮助调试内部驱动程序不正确配置或缺少服务结构。即,如果驱动程序加载但保持沉默而没有跟踪消息,则表示由于某些内核期望的服务结构信息缺失或故障,未执行探测。

22

您需要按照以下三个步骤操作。

1. 确保您的内核编译选项中包含CONFIG_DYNAMIC_DEBUG=y

cat /proc/config.gz | gunzip | grep CONFIG_DYNAMIC_DEBUG

如果没有的话,请重新编译您的内核,并启用CONFIG_DYNAMIC_DEBUG = y。
2)启动后,请检查debugfs是否已经挂载在某个位置。
mount | grep debugfs

大多数情况下,它会被挂载在 /sys/kernel/debug 中,如果没有,则可以手动挂载在任何地方,如下所示。
mount -t debugfs none /sys/kernel/debug

3) 现在启用您需要 dev_dbg() 日志的文件名。

echo 'file <driverfilename.c> +p'>/sys/kernel/debug/dynamic_debug/control

还有一些命令可以使用dynamic_debug/control,请查看https://www.kernel.org/doc/html/v4.11/admin-guide/dynamic-debug-howto.html

现在您应该能够获取调试信息。

如果您仍然无法看到您的消息,请启用prink级别。

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

如果未设置CONFIG_DYNAMIC_DEBUG选项,则dev_dbg/pr_debug可以转换为具有KERN_DEBUG级别的普通printk()语句。

但是,您需要在文件开头添加#define DEBUG, 或者在编译时添加-DDEBUG, 或者启用CONFIG_[SUBSYSTEM]_DEBUG=y。


7

我使用了以下命令来打开Android内核日志记录。我认为对于Linux也应该适用:

echo 'file <driverfilename.c> +p'>/sys/kernel/debug/dynamic_debug/control

可以在“dmesg”中查看驱动程序日志

谢谢 MJ


1
请参阅 https://www.kernel.org/doc/html/v4.11/admin-guide/dynamic-debug-howto.html。 - Carlo Wood

4
将 "debug" 添加到内核参数中将会提升内核事件日志级别到 KERN_DEBUG(级别 7),这将污染 kmsg 缓冲区并在整个内核代码中输出调试信息,而这通常不是我们在调试内核模块时想要的结果。同样,当我们通过 /proc/sys/kernel/printk 改变当前内核日志级别时,也是如此。
为了精细控制仅针对您的内核模块以上 KERN_ERR 的所有日志级别,而不破坏全局内核日志级别配置,请在您的模块代码开头添加以下行:
#undef dev_dbg
#undef dev_info
#undef dev_warn
#undef dev_notice

#define dev_dbg dev_err
#define dev_info dev_err
#define dev_warn dev_err
#define dev_notice dev_err

1
您可以通过执行以下命令手动挂载调试文件系统:

mount -t debugfs none /sys/kernel/debug

完成后,请执行以下操作:

ls /sys/kernel/debug

所有的调试信息和消息都会存储在那里,无需重新编译。
此外,您可以将此添加到 /etc/fstab 中,以便在重新启动时自动进行挂载。
如果您无论如何都要重新编译内核,那么可以在“Kernel Hacking”下启用“[*] Debug File System”。
祝你好运,希望一切顺利。

原始需求是“不要在内核打补丁/重新编译或驱动程序实现一些额外的东西,如debugfs”。 - Oleg Kokorin
仅供参考,因为这个答案是“enable dev_dbg”的谷歌搜索结果之一,然后必须在debug/dynamic/control中启用消息(https://www.kernel.org/doc/html/v4.15/admin-guide/dynamic-debug-howto.html)。 - Étienne

0

你感兴趣的驱动程序很可能已经导出了Kconfig选项以启用调试消息。在这种情况下,您可以通过在menuconfig中设置DEBUG_YOUR_DRIVER=yYOUR_DRIVER_DEBUG=y并重新构建内核来仅启用一个驱动程序的调试输出。搜索驱动程序名称,您将看到是否可用。

例如,对于NXP/Freescale i.MX pinctrl驱动程序,我只需将DEBUG_PINCTRL更改为y,然后查看dmesg以获取该驱动程序的调试日志。

这是我最快的方法。


1
不需要搞乱内核补丁/重新编译,这个细节我想你不需要知道吧? - Oleg Kokorin
嗨,感谢您的评论。其他一些答案也需要重建内核或修改驱动程序代码并重新构建它。我只是分享了对我有效的方法,并且很可能易于其他Buildroot/Yocto用户使用。 - Filip Kubicz
我添加了答案并不是因为你的答案有误,而是为了给那些通过搜索引擎来到这里的人提供另一个选择。 - Filip Kubicz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接