如何在 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__)
我尝试使用命令 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__)