如何在printk中使用变量作为格式字符串?

问题描述 投票:0回答:4

我尝试使用命令 printk。

我在互联网上找到的所有示例都是直接将字符串放入 printk 中,如下所示:

printk(KERN_INFO "Hello %s!", "World");

但是,我尝试替换“Hello %s!”使用这样的缓冲区:

char buf[] = "Hello %s!";
printk(KERN_INFO buf, "WORLD");

结果我得到了错误

error: expected ')' before 'buf'

我们应该如何在 printk 中使用变量并使用日志级别 KERN_INFO?

c linux-kernel printk
4个回答
6
投票

KERN_INFO
被定义为字符串常量 " " "6"。写作时

printk(KERN_INFO "Hello %s!", "World");

C 编译器根据 C 标准的要求自动连接三个字符串常量:

"\001" "6" "Hello %s!"

单个字符串常量。然而,这不适用于变量,就像buf

在这里:

char buf[] = "Hello %s!"; printk(KERN_INFO buf, "WORLD");

的工作是什么:

char buf[] = KERN_INFO "Hello %s!"; printk(buf, "WORLD");
    

2
投票

KERN_INFO

 是在 Linux 内核头文件中定义的宏,当预处理器运行时,它会扩展为字符串文字。当在 C 代码中相邻放置字符串文字时,它们会隐式连接;当在字符串文字之间放置变量时,这是一个语法错误。

如果您将代码预处理到文件中,您将更容易观察到这一点。


0
投票
可能的解决方法包含三个组件:一个可以生成具有特定日志级别的调试函数的宏,使用所需的日志级别创建此函数,另一个宏使用可变数量的参数调用创建的函数。

调用 LOGPRINTK(buf, "WORLD") 即可完成这项工作。

#include "stdarg.h" // a macro which can generate a loglevelfunction based on the loglevel // in kzalloc, do not forget the + 1 for the trailing zero #define GENERATE_LOGLEVEL_FUNCTION(loglevelstring) void loglevelfunc(char *fmt, ...) { \ char *modifiedfmt = NULL; \ va_list input; \ modifiedfmt = kzalloc((strlen(loglevelstring) + strlen(fmt) + 1 )*sizeof(char), GFP_KERNEL) ; \ if (modifiedfmt) { \ strcpy(modifiedfmt, loglevelstring); \ va_start(input, fmt); \ strcat(modifiedfmt, fmt); \ vprintk(modifiedfmt, input) ; \ va_end(input); \ kfree(modifiedfmt); \ modifiedfmt = NULL; \ } \ } // this line generates the log level function, with loglevel KERN_INFO GENERATE_LOGLEVEL_FUNCTION(KERN_INFO) // finally, the function we want #define LOGPRINTK(...) loglevelfunc(__VA_ARGS__)
    

0
投票
请检查

struct va_format。它允许您将现有格式字符串和变量参数作为变量传递到新格式字符串中。用法示例:

va_list args; struct va_format vaf = { .fmt = format, }; va_start(args, format); vaf.va = &args; printk(KERN_DEBUG "[MY PREFIX] %pV", &vaf); va_end(args);
    
© www.soinside.com 2019 - 2024. All rights reserved.