Linux kernel printk log level

1. Log level 的定义

在 Linux 内核里,printk 经常用来格式化输出,类似于常见的 printf。需要注意的是,printk 有一个 log level 的参数,使用的时候经常是这样的:

printk(KERN_WARNING "Trying to free nonexistent resource");

浏览内核头文件,include/linux/kern_levels.h 里有这样的定义:

#define KERN_EMERG      KERN_SOH "0"    /* system is unusable */
#define KERN_ALERT      KERN_SOH "1"    /* action must be taken immediately */
#define KERN_CRIT       KERN_SOH "2"    /* critical conditions */
#define KERN_ERR        KERN_SOH "3"    /* error conditions */
#define KERN_WARNING    KERN_SOH "4"    /* warning conditions */
#define KERN_NOTICE     KERN_SOH "5"    /* normal but significant condition */
#define KERN_INFO       KERN_SOH "6"    /* informational */
#define KERN_DEBUG      KERN_SOH "7"    /* debug-level messages */

使用的时候要选择合适的 level。

既然打印时指定了不同的 log level,那系统运行时,可以屏蔽到一些打印,从而实现日志的过滤。默认的过滤级别是 CONSOLE_LOGLEVEL_DEFAULT。这个值定义在 defconfig 里。

如果在调用 printk 时没有指定,会使用默认的 MESSAGE_LOGLEVEL_DEFAULT。这个值同样定义在 defconfig 里。

2. 调整 log level

系统运行过程中,可以通过 /proc/sys/kernel/printk 文件,来查看和调整运行时的 log level:

$ cat /proc/sys/kernel/printk
4       4       1       7

这四个数值,分别是:

  1. 目前的控制台的 log level。日志的 log level 小于(优先级高于)这个值的时候,才会输出;
  2. 默认的 log level,如果调用 printk 时没有指定的话;
  3. 第 1 个参数可以设置的最小值;
  4. boot 时的 log level,尽量大(优先级低)一些,从而可以看到更多启动日志;

如果要修改,用 echo 就可以了。

3. Kernel 里的相关代码

log level 数组定义 @ kernel/printk/printk.c

int console_printk[4] = {
        CONSOLE_LOGLEVEL_DEFAULT,       /* console_loglevel */
        MESSAGE_LOGLEVEL_DEFAULT,       /* default_message_loglevel */
        CONSOLE_LOGLEVEL_MIN,           /* minimum_console_loglevel */
        CONSOLE_LOGLEVEL_DEFAULT,       /* default_console_loglevel */
};
EXPORT_SYMBOL_GPL(console_printk);

console_printk @ include/linux/printk.h

extern int console_printk[];
#define console_loglevel (console_printk[0])

读写 /proc/sys/kernel/printk 的实现 @ kernel/sysctl.c

{
    .procname       = "printk",
    .data           = &console_loglevel,
    ...
},

参考资料

  • Documentation/admin-guide/sysctl/kernel.rst, printk
  • man 2 syslog

Read More: