我尝试使用命令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
定义为字符串常量"\001"6"。写作时
printk(KERN_INFO "Hello %s!", "World");
C 编译器根据 C 标准的要求自动连接三个字符串常量:
" 01" "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__)