Linux内核调试技术之printk

  • Post author:
  • Post category:linux




前言

printk是Linux内核提供的打印函数,类似于用户态的printf,一个较大的差别在于printk支持多种日志级别,从而允许printk根据消息的等级选择性进行打印。printk打印的日志通常会显示在控制台上或者输出到日志文件(一般为/var/log/messages)中。



printk函数使用

在使用printk时,会将日志级别放到最开始的位置,使用方式如下:

printk(log_level "message...");

若未设置日志级别,printk默认使用内核定义的全局变量

default_message_loglevel

作为的默认打印的日志级别。



日志级别

日志级别用来控制printk打印的这条信息是否在终端上显示,当日志级别的数值小于控制台级别时,printk要打印的信息才会在控制台打印出来,否则不会显示在控制台。Linux内核定义的printk日志级别为:

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



运行时调整日志级别

Linux系统支持在运行时,通过proc文件系统查看和调整内核日志的输出等级。查看当前控制台的打印级别的命令如下:

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

其中,4个数字代表的含义依次为:控制台的日志级别、默认消息日志级别、最小控制台日志级别和默认控制台日志级别。



修改当前日志级别

执行以下命令,可以修改当前控制态的日志级别:

echo "新的打印级别  4    1    7" >/proc/sys/kernel/printk



其它用法

为了方便开发者使用,内核还提供了pr_xx和dev_xx系列的打印接口,本质上,它们都是基于printk实现的,其中pr_xx系列函数简化了日志级别的使用;dev_xx系列函数可以用于设备驱动程序中,便于打印设备相关的信息。



pr_xx系列函数

pr_xx系列函数定义在include/linux/printk.h文件中,函数定义如下:

#define pr_emerg(fmt, ...) \
        printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
#define pr_alert(fmt, ...) \
        printk(KERN_ALERT pr_fmt(fmt), ##__VA_ARGS__)
#define pr_crit(fmt, ...) \
        printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
#define pr_err(fmt, ...) \
        printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
#define pr_warning(fmt, ...) \
        printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
#define pr_notice(fmt, ...) \
        printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
#define pr_info(fmt, ...) \
        printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
#define pr_cont(fmt, ...) \
	printk(KERN_CONT fmt, ##__VA_ARGS__)



dev_xx系列函数

dev_xx系列函数定义在include/linux/dev_printk.h文件中,函数定义如下:

#define dev_emerg(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_emerg, KERN_EMERG, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_crit(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_crit, KERN_CRIT, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_alert(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_alert, KERN_ALERT, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_err(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_warn(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_warn, KERN_WARNING, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_notice(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_notice, KERN_NOTICE, dev, dev_fmt(fmt), ##__VA_ARGS__)
#define dev_info(dev, fmt, ...) \
	dev_printk_index_wrap(_dev_info, KERN_INFO, dev, dev_fmt(fmt), ##__VA_ARGS__)



相关参考

  • 《奔跑吧,Linux内核》



版权声明:本文为anyegongjuezjd原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。