如何找到哪个函数打印 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_*()
家庭有这样的设施。
是否可以找到在哪个函数 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_*()
家庭有这样的设施。