问题描述:最近这两天再调试 platform 驱动,程序老是有点小问题,得不到自己想要的结果,突然意识到内核调试重要性,重新整理一下 printk 基本用法。内核通过
printk() 输出相关信息,在调用 printk() 函数时必须要指定日志级别。
1、printk 日志等级
在 include/linux/kernel.h 中定义了如下几个日志级别
<span style="font-family:Microsoft YaHei;font-size:12px;">#define KERN_EMERG "<0>" /* 系统崩溃 */ #define KERN_ALERT "<1>" /* 必须紧急处理 */ #define KERN_CRIT "<2>" /* 临界条件,严重的硬软件错误 */ #define KERN_ERR "<3>" /* 报告错误 */ #define KERN_WARNING "<4>" /* 警告 */ #define KERN_NOTICE "<5>" /* 普通但还是须注意 */ #define KERN_INFO "<6>" /* 信息 */ #define KERN_DEBUG "<7>" /* 调试信息 */</span>
这里也可以看出数值越小,其紧急和严重程度就越高。
接下来,我们来看 kernel/printk.c 文件:
/* printk's without a loglevel use this.. */ #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */ /* 因此,如果未在 printk() 中指定日志级别,系统将默认采用4级 */ /* We show everything that is MORE important than this.. */ #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */ DECLARE_WAIT_QUEUE_HEAD(log_wait); int console_printk[4] = { DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */ DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */ MINIMUM_CONSOLE_LOGLEVEL, /* minimum_console_loglevel */ DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */ }; /* 这4组数字可以在/proc/sys/kernel/printk中更改 */
在 /proc/sys/kernel/printk 会显示4个数值(可由 echo 修改),分别表示
当前控制台日志级别;
未明确指定日志级别的默认消息日志级别;
最小(最高)允许设置的控制台日志级别;
引导时默认的日志级别;
当 printk()中指定的级别 (数值上)小于 当前控制台日志级别(前面说过,数值越小,严重性越高)时,printk 的信息(要有\n符)就会在控制台上显示。但无论当前控制台日志级别是何值,通过 dmesg 总能查看。
系统的日志记录工具有两种主要的:syslog 和 klog。
syslog 用于执行系统日志记录活动,系统进程显示为 syslogd。配置文件是/etc/syslog.conf。如果在配置文件中把kern.*这一行前的#号去掉,那么printk的信息也会输出到控制台。其守护进程是syslogd。syslogd 进程从一组日志源(如 /dev/log 和 /dev/klog )中读取数据,并按照 /etc/syslog.conf 中的说明处理这些日志消息。
2、printk 输出格式符
如果变量类型是 , 使用 prink 的格式说明符 :
int %d 或者 %x( 注: %d 是十进制, %x 是十六进制 )
unsigned int %u 或者 %x
long %ld 或者 %lx
unsigned long %lu 或者 %lx
long long %lld 或者 %llx
unsigned long long %llu 或者 %llx
size_t
%zu 或者 %zx
ssize_t %zd 或者 %zx
原始指针值必须用 %p 输出。
u64,即(unsigned long log n),必须用 %llu 或者 %llx 输出,如:
printk("%llu", (unsigned long long)u64_var);
s64,即(long long),必须用 %lld 或者 %llx 输出,如 :
printk("%lld", (long long)s64_var);