启用 linux 内核驱动程序 dev_dbg 调试消息

Posted

技术标签:

【中文标题】启用 linux 内核驱动程序 dev_dbg 调试消息【英文标题】:enable linux kernel driver dev_dbg debug messages 【发布时间】:2018-11-03 09:30:39 【问题描述】:

是否有一种最简单的方法可以启用 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,所以它肯定很接近。谢谢

【问题讨论】:

kernel.org/doc/html/v4.11/dev-tools/gdb-kernel-debugging.html 【参考方案1】:

无需安装/配置 syslog/etc 即可接收dev_dbg 消息的最简单方法,似乎需要执行以下步骤:

    bootargs内核参数中提供debug密钥

    在驱动程序文件的第一行附加 #define DEBUG - 如果驱动程序是单个文件并且使用通用 Makefile,或者如果驱动程序包含多个源文件,通常有自己的 Makefile

    在内核启动时,提示似乎通过执行dmesg -n 8echo 8 > /proc/sys/kernel/printk 来启用调试级别消息

    如果模块使用insmod <driver name>modprobe <driver name> 命令加载驱动程序,或者如果驱动程序集成到内核中,则插入命令可能会有所不同。

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

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

旁注:

如果 DTS 将有驱动记录分配,手动重复驱动分配将导致错误 - 如果是 i2c 子系统 - 错误 EBUSY (-16),驱动将在命令提示符之前分配,并且dmesg 消息将被限制为默认级别(通常仅限 dev_info

如果驱动程序已由DTS 分配,并且无法从树源中临时排除它 - 在debug(跟踪)级别消息激活后再次分离和重新附加它很有用

对于 i2c 子系统,它需要执行一个命令:

echo <driver name> > /sys/bus/i2c/drivers/<drivername>/unbind

然后

echo <driver name> > /sys/bus/i2c/drivers/<drivername>/bind

警告:

内核驱动程序跟踪机制无助于调试内部驱动程序配置不当或缺少服务结构。即,如果驱动程序已加载但保持沉默且没有任何跟踪消息,则意味着 probe 由于某些内核预期的服务结构信息丢失或错误而从未执行过

【讨论】:

【参考方案2】:

您需要遵循以下三个步骤。

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

现在你应该得到你的调试了。

如果您仍然没有看到您的消息,请启用恶作剧级别

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

【讨论】:

【参考方案3】:

我使用以下命令打开 android 内核日志。我认为对于 Linux 来说它应该可以工作:

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

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

谢谢 乔丹

【讨论】:

见kernel.org/doc/html/v4.11/admin-guide/dynamic-debug-howto.html【参考方案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

【讨论】:

【参考方案5】:

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

mount -t debugfs none /sys/kernel/debug

完成后,做:

ls /sys/kernel/debug

所有调试信息和消息都将存储在那里,无需重新编译。

另外,您可以在 /etc/fstab 下添加此项,以在重新启动时自动挂载。

...如果你还是要重新编译你的内核,那么你可以在“Kernel Hacking”下启用“[*] Debug File System”

祝你好运,希望一切顺利。

【讨论】:

“不搞乱内核补丁/重新编译或驱动程序实现一些额外的东西,如 debugfs”是最初的要求 仅供参考,因为此答案是“启用 dev_dbg”的第一个谷歌点击之一,因此必须在调试/动态/控制 (kernel.org/doc/html/v4.15/admin-guide/dynamic-debug-howto.html) 中启用消息。【参考方案6】:

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

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

这对我来说是最快的方法。

【讨论】:

“不搞乱内核补丁/重新编译”细节不适合你,我想? 您好,感谢您的评论。其他一些答案也需要重建内核,或修改驱动程序的代码并重建它。我只是分享了对我有用的东西,并且可能很容易被其他 Buildroot/Yocto 用户使用。 我添加答案不是因为您的答案错误;而是为从搜索引擎来到这里的人提供另一种选择。

以上是关于启用 linux 内核驱动程序 dev_dbg 调试消息的主要内容,如果未能解决你的问题,请参考以下文章

高性能linux服务器内核调优

Perf -- Linux下的系统性能调优工具

Perf -- Linux下的系统性能调优工具

服务器调优

Linux系统调优1

Perf -- Linux下的系统性能调优工具,第 1 部分