我尝试使用命令 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
被定义为字符串常量 " " "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");
KERN_INFO
是在 Linux 内核头文件中定义的宏,当预处理器运行时,它会扩展为字符串文字。当在 C 代码中相邻放置字符串文字时,它们会隐式连接;当在字符串文字之间放置变量时,这是一个语法错误。如果您将代码预处理到文件中,您将更容易观察到这一点。
调用 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__)
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);