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

How to use a variable as a format string in printk?

我尝试使用命令 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?

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

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

KERN_INFO定义为字符串常量“\001”“6”。写作时

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

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

"[=11=]1" "6" "Hello %s!"

到单个字符串常量。但是,这 不适用于 变量,例如 buf 在这里:

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

的工作是:

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

一个可能的解决方法包含三个部分:一个可以生成具有特定日志级别的调试函数的宏,使用所需的日志级别创建此函数,另一个调用具有可变数量参数的已创建函数的宏。
调用 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__)