如何找到哪个函数打印 printk 语句?

How to find which function prints printk statement?

是否可以找到在哪个函数 printk 中执行的方法? 我知道我可以将 __function__ 添加到我的 printk 中以获取此信息,但我正在处理大型项目并且手动将其添加到所有 printk 有点不可能。

也许我应该在代码中添加一些宏或使用一些 linux 命令?

你可以用一些宏来做到这一点(至少用printf,但原理和printk是一样的):

#include <stdio.h>

/* redefine printf for the rest of file. */
#define printf(...) \ 
do { \
    printf("%s: %d:\t", __FILE__, __LINE__);\    
    printf(__VA_ARGS__);\
} while (0)

/* after this point, each call to printf will be replaced by two. */


int main(void)
{
    printf("Hello\n");
    return 0;
}

将打印(从 https://tio.run/#c-gcc 测试):

.code.tio.c: 12:    Hello 

而不只是

Hello

因为我们在谈论 Linux 内核编程,所以有几种方法可以实现这一点。最糟糕的是定义自定义宏,您可以在其中添加一些额外的内容来打印。现在,让我们考虑更好的方法。

方法一 如果您有兴趣将函数名称仅放入消息的子集,假设出于调试目的,最好的选择是启用 Dynamic Debug 选项并使用特殊宏而不是直接调用 printk,即 pr_debug()dev_dbg()netdev_dbg() 等等。

它将允许您在 运行 时间打开和关闭任何单个消息,同时启用或不打印 __func__

方法二 另一种方法,如果你想为宏系列启用额外的参数,例如 pr_*()dev_*(),你可以在每个模块的最开始定义特殊的宏,或者,如果你愿意,包括header,虽然它必须是每个 C-file 中的第一个。请参阅 ipmi_msghandler.c 中的示例:

#define pr_fmt(fmt) "%s" fmt, "IPMI message handler: "
#define dev_fmt pr_fmt

它可以很容易地转化为

#define pr_fmt(fmt) "%s(): " fmt, __func__
#define dev_fmt pr_fmt

这种方法的好处是可以为不同的模块设置不同的前缀,例如使用它们的文件名,并且它将应用于同一宏系列的所有消息。

缺点是只有pr_*()dev_*()家庭有这样的设施。