Home | Projects | Notes > Linux Device Drivers > Debugging with printk
& Kernel Log Levels
printk
& Kernel Log Levels
printk
print
is one of the best debugging tools we have in user-level applications.
When you work in kernel space, you will not have any access to the C standard library functions like printf
or scanf
.
As their counterpart, the kernel has its own printf
-like API called printk
, where the letter k
signifies "Kernel space printing".
Examples;
xxxxxxxxxx
41printf("User space.\n");
2printk("Kernel space.\n"); /* Kernel space */
3printf("data1 = %d, data2 = %d\n, d1, d2");
4printk("data1 = %d, data2 = %d\n, d1, d2"); /* Kernel space */
When using printk
, the message will go into the kernel ring buffer (a.k.a. Kernel log) and we can print and control the kernel ring buffer using the command dmesg
.
To check the latest 5 kernel messages:
xxxxxxxxxx
11dmesg | tail -5
To check the first 20 kernel messages:
xxxxxxxxxx
11dmesg | head -20
printk
format specifiers
xxxxxxxxxx
141Variable Type printk Format Specifier
2================== =======================
3int %d or %x
4unsigned int %u or %x
5long %ld or %lx
6unsigned long %lu or %lx
7long long %lld or %llx
8unsigned long long %llu or %llx
9size_t %zu or %zx
10ssize_t %zd or %zx
11s32 %d or %x
12u32 %u or %x
13s64 %lld or %llx
14u64 %llu or %llx
printk
does not support floating-point formats (%e
,%f
,%g
).
[!] Reference: https://www.kernel.org/doc/Documentation/printk-formats.txt
Based on the kernel log level you can control the priority of the printk
messages.
There are 8 log levels
The lower the level number, the higher the priority
The default printk
log level or priority is usually set to 4. (i.e., KERN_WARNING
)
xxxxxxxxxx
151/* include/linux/kern_levels.h */
2
3/* ASCII Start Of Header */
4
5
6/* system is unstable */
7/* action must be taken immediately */
8/* critical conditions */
9/* error conditions */
10/* warning conditions */
11/* normal but significant condition */
12/* informational */
13/* debug-level messages */
14
15/* the default kernel loglevel */
The log level will be used by the kernel to understand the priority of the message. Based on the priority the kernel will decide whether the message should be presented to the user immediately by printing directly on to the console.
All kernel messages will have their own log level.
You may have to specify the log level while using printk
. If not specified, the kernel will add the default log level set by the kernel config item CONFIG_MESSAGE_LOGLEVEL_DEFAULT
whose value is 4.
So, the following statement
xxxxxxxxxx
11prink("Kernel space\n");
is equivalent to
xxxxxxxxxx
31prink(KERN_WARNING "Kernel space\n");
2// ------------ --------------
3// Log level String arg
Notice that there's NO comma (,) between the log level and the string argument!
Default message log level can be configured via the kernel menuconfig (make ARCH=arm menuconfig
)
There is another log level we need to consider; the current console log level.
The kernel message log level will be compared with the current console log level. If the kernel message log level is lower (i.e., higher priority) than the current console log level, the message will be directly printed on the current console.
By default, the console log level will have the value of config item CONFIG_CONSOLE_LOGLEVEL_DEFAULT
whose default value is set to 7. This value can be changed via the kernel menuconfig or running commands.
To check the current console log level status, run
xxxxxxxxxx
21cat /proc/sys/kernel/printk
27 4 1 7
The results shows the current, default, minimum and boot-time-default log levels.
pr_info
(i.e., KERN_INFO
level) used in the hello world LKM is of log level 6. This is why the message is getting printed when the LKM gets inserted into the kernel.
At run-time, you can change the current console log level (for example to 6) by running the following command:
xxxxxxxxxx
21sudo -s
2echo 6 > /proc/sys/kernel/prink
Now, if you check the current console log level:
xxxxxxxxxx
21cat /proc/sys/kernel/printk
26 4 1 7
The current console log level has changed from 7 to 6.
Since the current console log level is now the same as pr_info
(i.e., KERN_INFO
level), the message will not get printed when the hello world LKM gets inserted into the kernel.
prink
wrappers (Defined in include/linux/printk.h
)
Name | Log Level | Alias Function |
---|---|---|
KERN_EMERG | "0" | pr_emerg |
KERN_ALERT | "1" | pr_alert |
KERN_CRIT | "2" | pr_crit |
KERN_ERR | "3" | pr_err |
KERN_WARNING | "4" | pr_warning |
KERN_NOTICE | "5" | pr_notice |
KERN_INFO | "6" | pr_info |
KERN_DEBUG | "7" | pr_debug (works only if DEBUG is defined) |
KERN_DEFAULT | "" | - |
pr_err
- Useful for reporting errors
pr_info
- Useful for printing general information
pr_warning
- Useful for reporting warning
pr_alert
,pr_crit
- Useful for reporting critical situations
For example:
xxxxxxxxxx
11printk(KERN_INFO "Kernel version 4.14\n");
Can be re-written as
xxxxxxxxxx
11pr_info("Kernel version 4.14\n");