【问题标题】:How to find which function prints printk statement?如何找到打印 printk 语句的函数?
【发布时间】:2020-01-05 08:55:51
【问题描述】:

有没有办法找到在哪个函数printk 被执行? 我知道我可以将__function__ 添加到我的printk 以获取此信息,但我正在处理大型项目,并且无法手动将其添加到所有printk

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

【问题讨论】:

  • 最简单的方法是使用动态调试功能以及pr_debug()dev_dbg() 等。动态调试允许您在运行时切换功能打印。对于pr_*() 宏的其他风格,通常没有意义,因为我们正在讨论内核编程。

标签: c linux-kernel printk


【解决方案1】:

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

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

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

方法 2。 另一种方法是,如果你想为宏系列启用额外的参数,例如pr_*()dev_*(),你可以在每个模块的开头定义特殊的宏,或者,如果你愿意,可以从头文件中包含,尽管它必须是每个 C 文件中的第一个。参见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_*()家庭有这样的设施。

【讨论】:

    【解决方案2】:

    你可以用一些宏来做到这一点(至少用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 内核有关,其中存在其他工具。
    • 使用两个 printf() 认为它们将被合并是一个巨大的错误并且不再起作用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-27
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    • 2014-10-24
    • 1970-01-01
    相关资源
    最近更新 更多