Linux内核调试利器——printk

来源:互联网 发布:双色球参选数据 编辑:程序博客网 时间:2024/05/16 16:11

在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/messagesSep 28 10:12:47 ubuntu-kernel kernel: [  742.327807] Goodbye, linux kernelSep 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

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

  • 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

0 0