您的位置:首页 > 运维架构 > Linux

Linux内核调试利器——printk

2015-09-29 14:32 681 查看
在Linux开发环境下,打印log一直是最有效的调试方式,内核开发也不例外。

先看一下下面这段代码:

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

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Wang Shuxiao");

static int hello_init(void)
{
printk(KERN_INFO "hello, linux kernel");
return 0;
}

static void hello_exit(void)
{
printk(KERN_INFO "Goodbye, linux kernel");
}

module_init(hello_init);
module_exit(hello_exit);


将其编译成hello.ko模块,反复insmod/rmmod之后发现,我在insmod的时候,它打印出”Goodbye, linux kernel”;而在rmmod时,它打印出”hello, linux kernel”,奇了个怪!

bookxiao@ubuntu-kernel:~$ tail -f /var/log/messages
Sep 28 10:12:47 ubuntu-kernel kernel: [  742.327807] Goodbye, linux kernel
Sep 28 10:14:05 ubuntu-kernel kernel: [  838.865803] hello, linux kernel


后来,在Linux Device Driver 里面看到这么一句话:

Based on the loglevel, the kernel may print the message to the current console, be it a text-mode terminal, a serial port, or a parallel printer. If the priority is less than the integer variable console_loglevel, the message is delivered to the console one line at a time (nothing is sent unless a trailing newline is provided).

原来是printk里面未在末尾添加换行符,导致不能及时flush到终端。修复后即正常。

下面是内核日志系统的基本框架和使用方法。



这是一个典型的生产者-消费者模型。

printk将消息写入一个循环buffer,大小在编译内核时(CONFIG_LOG_BUF_SHIFT)指定。当buffer满时,会覆盖掉开始处的(最老的)的消息。ring buffer的设计可以使读写操作无需同步:读操作总是发生在队列头,写操作总是发生在队列尾。因此,可以在任何上下文中调用printk:可以在进程上下文中调用,也可以在中断上下文中调用,甚至在持有锁的情况下调用。

消费者通过syslog()系统调用或者直接读”/proc/kmsg”文件,即可从ring buffer读取数据,若无数据可读,则会阻塞。klogd进程采用的就是第二种方法,将内核消息读出来,并发送到syslogd进程。

此外,printk会判断消息级别和系统当前console_loglevel的值,如果消息级别高于console loglevel,会将消息同时输出到控制终端。

注意,上面的syslog()指的是系统调用,而非glibc(用户空间)的syslog()。这两个的作用是不同的:内核里的syslog作为消费者,从ring buffer读取数据(定义在linux-source/kernel/printk.c中的);用户空间的syslog()则是一个工具,可以向syslogd(或rsyslogd)进程写入数据,syslogd再将数据dispatch到不同的文件(根据/etc/syslog.conf)。默认情况下,从klogd发送过来的内核消息,会被写入到/var/log/messages文件。

/* kernel/printk.c */
SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
{
return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
}


参考资料

[1] Linux kernel development, Robert Love

[2] Advanced Programming in UNIX Environment, 3rd

[3] Linux Device Driver, 3rd
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux kernel 开发 内核