Reputation: 199
I try to use the command printk.
All the examples I can find on the internet is by putting a string directly in the printk like this:
printk(KERN_INFO "Hello %s!", "World");
However, I tried to replace the "Hello %s!" using a buffer like this:
char buf[] = "Hello %s!";
printk(KERN_INFO buf, "WORLD");
It turns out that I get the error
error: expected ')' before 'buf'
What should we do to using a variable in printk and also use a log level KERN_INFO?
Upvotes: 5
Views: 6409
Reputation: 121
Please check struct va_format. It lets you pass existing format string and variable arguments as variable into new format string. Example usage:
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);
Upvotes: 0
Reputation: 139
A possible workaround with three components: a macro which can generate a debug function with a specific loglevel, creation of this function with the loglevel wanted, another macro calling the created function with a variable number of arguments.
Calling LOGPRINTK(buf, "WORLD") does the job.
#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__)
Upvotes: 0
Reputation: 18420
KERN_INFO
is defined as string constants "\001" "6". When writing
printk(KERN_INFO "Hello %s!", "World");
the c compiler automatically concatenates the three string constants as required by the C standard:
"\001" "6" "Hello %s!"
to a single string constant. This, however, does not work with a variable, like buf
is here:
char buf[] = "Hello %s!";
printk(KERN_INFO buf, "WORLD");
What will work is:
char buf[] = KERN_INFO "Hello %s!";
printk(buf, "WORLD");
Upvotes: 6
Reputation: 21542
KERN_INFO
is a macro defined in the Linux kernel headers that expands to a string literal when the preprocessor runs. When placing string literals adjacently in C code they are implicitly concatenated; when placing a variable between string literals, it's a syntax error.
If you preprocess your code to a file, you will observe this more easily.
Upvotes: 2