details of printk

详解printk

clip_image002

比较简单的一个内核程序:


#include
<linux/init.h>
#include
<linux/module.h>

MODULE_LICENSE("Dual
BSD/GPL"
);

#define KERN_LEVEL_NO
"<0>"

static int
hello_init(void)
{

printk(KERN_LEVEL_NO "Hello ,
world\n"
);

return
0;
}

static void
hello_exit(void)
{

printk(KERN_LEVEL_NO "Goodbye , curl
world\n"
);
}

module_init(hello_init);
module_exit(hello_exit);

关于printk

函数printk的使用方法和printf相似,用于内核打印消息。printk根据日志级别(loglevel)对消息进行分类。

日志级别用宏定义,日志级别宏展开为一个字符串,在编译时由预处理器将它和消息文本拼接成一个字符串,因此printk 函数中日志级别宏和格式字符串间不能有逗号。

 

比如下面是两个printk的例子,一个用于打印调试信息,另一个用于打印临界条件信息。


printk(KERN_DEBUG "Here
I am: %s:%i\n"
, _ _FILE_ _, _ _LINE_ _);
printk(KERN_CRIT "I'm
trashed; giving up on %p\n"
, ptr);

 

       我们可以查看kern_level.h文件(/usr/src/kernels/`uname -r`/include/linux,


#ifndef
__KERN_LEVELS_H__
#define
__KERN_LEVELS_H__

#define KERN_SOH
"\001"
/* ASCII Start Of Header */
#define KERN_SOH_ASCII '\001'

#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 */

#define KERN_DEFAULT KERN_SOH "d" /* the default kernel
loglevel */

/*
*
Annotation for a "continued" line of log printout (only done after
a
* line
that had no enclosing \n). Only to be used by core/arch
code
*
during early bootup (a continued line is not SMP-safe
otherwise).
*/
#define KERN_CONT
""

#endif

 

内核可把消息打印到当前控制台上,可以指定控制台为字符模式的终端或打印机等。默认情况下,控制台就是当前的虚拟终端。

为了更好地控制不同级别的信息显示在控制台上,内核设置了控制台的日志级别console_loglevelprintk日志级别的作用是打印一定级别的消息,与之类似,控制台只显示一定级别的消息。

当日志级别小于console_loglevel时,消息才能显示出来。控制台相应的日志级别定义如下:

如果系统运行了klogdsyslogd,则无论console_loglevel为何值,内核消息都将追加到/var/log/messages中。如果klogd没有运行,消息不会传递到用户空间,只能查看/proc/kmsg。其中syslogd负责记录系统运作中,kernel或应用程式产生的各种讯息。这些讯息被写入到系统的纪录档中,让管理人员,进行故障排除、追踪尝试非法入侵的使用者、进行使用者的分析等等。而kernel产生的讯息交由klogd处理,klogd再交由syslogd处理。

所以如果需要看到相关信息,我们需要安装yum install klogsyslog

Fedora使用的syslogd叫做rsyslogd,配置文件为/etc/rsyslog.conf,在该文件中指定了syslog记录日志的信息来源、信息类型以及保存位置。

klogd所记录的信息会比syslogd 的顺序优先,原因是klogd所记录的是尚未进入操作系统的信息,但其实一开始的这些信息并不是由klogd所记录的,而是自加载kernel 时,就已经开始记录的。在系统尚未进入操作系统阶段,还在加载kernel及执行initrd时,会将信息先记录在/proc/kmsg文件中(因为在initrd阶段没有实体硬盘可供记录),等进入操作系统执行完klogd后,klogd再将/proc/kmsg的所有内容全数填入/var/log/message文件中,这也是为何在/var/log/message文件的一开始,依然可以看到刚开机在加载kernel以及initrd阶段的信息。

       查看/proc/kmsg如下所示(每次操作模块时都有消息输出):

clip_image004