使用printk进行内核调试的方法

转载 2012年03月22日 12:28:03

FROM:http://hi.baidu.com/bitzsk/blog/item/a242ed4588cb888ab3b7dccc.html

---------------------------------------------------------------------------------------------------------------

在编程时候,最简单的调试莫过于用打印语句打印出结果从而判断BUG出在哪儿,但是内核调试与用户程序调试相比难度要大很多,原因是有二:首先,虽然Linux是用C语言写的,但是内核中不认识库文件中的printf函数。其次,内核程序运行在内核空间,而用户程序运行在用户空间,我们的打印语句要将内存的内容输出到控制台打印出来。因此,我们要想办法将“打印”这个操作转到内核空间中对内核代码进行跟踪。

内核通过printk函数解决了第一个难点。它是可以运行在内核空间的打印函数,相当于C语言中的printf函数。例如:

printk(KERN_ALERT “hello world\n”);

注意,KERN_ALERT与上引号中间有空格但是没有逗号。

关于printk的具体用法请参考printk()函数的使用

printk输出的信息在哪里?

由于Linux都带有syslogklog进程(参考linux系统管理中的日志管理),如果没有修改过日志配置文件,这些信息会输出到/var/log/messages中。

Linux中,内核是按模块划分的,一般包括进程管理,内存管理,文件系统,设备控制,网络等。模块(module)是在内核空间运行的程序,实际上是一种目标对象文件,没有链接,不能独立运行,但是可以装载到系统中作为内核的一部分运行,从而可以动态扩充内核的功能。模块最主要的用处就是用来实现设备驱动程序。

使用模块的优点: 
1,
将来修改内核时,不必全部重新编译整个内核,可节省不少时间 
2,
系统中如果需要使用新模块,不必重新编译内核,只要插入相应的模块即可

因此,我们可以将“打印”操作作为一个内核模块,printk语句就可以打印出内核空间的内容。

下面是一个简单的内核模块示例:

#include<linux/init.h>
   2 #include<linux/module.h>
   3 #include<linux/kernel.h>
   4 MODULE_LICENSE("Dual BSD/GPL");
   5 
   6 static int hello_init(void)
   7 {
   8 printk(KERN_ALERT "Hello world\n");
   9 return 0;
10 }
11 
12 
13 static int hello_exit(void)
14 {
15 printk(KERN_ALERT "Goodbye,cruel world\n");
16 return 0;
17 }
18 module_init(hello_init);
19 module_exit(hello_exit);

 
使用make来编译Makefile文件,然后以root身份来执行插入模块卸载模块。通过dmesg命令来查看printk输出的内容。下面是Makefile文件:

#Makefile 
   2 obj-+= hellomodule.#产生hellomod模块的目标文件
   3 CURRENT_PATH := $(shell pwd) #模块所在的当前路径
   4 LINUX_KERNEL := $(shell uname -r)#Linux内核源代码版本
   5 #LINUX_KERNEL_PATH := /usr/src/linux-headers-$(LINUX_KERNEL) #Linux内核源代码的绝对路径
   6 LINUX_KERNEL_PATH := /lib/modules/$(LINUX_KERNEL)/build
   7 all:
   8 make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules #编译模块了
   9 clean:
10 make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean #清理

 
 

查看printk输出的信息,可以先用locate命令来查找messages文件:

locate messages

看看/var/log/messages下是否有这个文件,有的话就用tail命令看该文件的最后内容:

tail[option] messages

也可以直接使用cat 命令:

cat /var/log/messages

or

cat /proc/kmsg (这个文件可能不存在)

注意,上面的命令有的需要root身份才能执行。

如果启动了syslogd的话(通常是有的),可以通过/var/log/messages查看printk输出的信息。也可以通过修改/etc/syslog.conf使其将信息输出到其它文件。



使用klogd -f 命令或修改/etc/syslog.conf将记录写到另一个文件中.

linux内核printk调试

linux内核printk调试(摘录《Linux安全体系分析与编程》) linux内核printk调试(摘录《Linux安全体系分析与编程》)1  printk及控制台的日志级别函数printk的使用...
  • catamout
  • catamout
  • 2010年03月15日 09:47
  • 15481

printk 使用方法

内核通过 printk() 输出的信息具有日志级别,日志级别是通过在 printk() 输出的字符串前加一个带尖括号的整数来控制的,如 printk("Hello, world!/n");。内核中共提...

printk的用法

printk的用法 内核通过 printk() 输出的信息具有日志级别,日志级别是通过在 printk() 输出的字符串前加一个带尖括号的整数来控制的,如 printk("Hello, world!\...
  • eydwyz
  • eydwyz
  • 2016年11月05日 13:14
  • 837

printk信息打印到指定文件 终端 网络

有的时候调试内核程序,经常要将信息打印到其他地方如指定文件或终端还有网络,  网络的话dreanice版主写过个netconsole我这里就不说了... 打印到文件:     ...
  • yyp872
  • yyp872
  • 2013年06月06日 20:59
  • 1125

虚拟机上Ubantu输出printk信息到指定文件

设置ubuntu让它从串口0输出printk信息 1、设置vmware添加serial port, 使用文件作为串口 2、启动ubuntu,修改/etc/default/grub GRUB_CM...

printk

在编写应用程序时,我们可以通过printf打印输出一些信息用来调试程序,Linux内核也提供了类似的函数printk,和printf不同的是,printk提供了输出日志级别,日志级别有: KERN_E...

printk()函数的总结

printk()函数的总结          我们在使用printk()函数中使用日志级别为的是使编程人员在编程过程中自定义地进行信息的输出,更加容易地掌握系统当前的状况。对程序的调试起到了很重...

Linux内核printk实现

基于MTK 6595分析,内核版本3.10.5 1 Printk函数分析 内核为Printk维护一个环形缓冲区,其大小为: #define __LOG_BUF_LEN (1 大小可以通过C...

printk打印log过多会导致performance下降

当遇到performance导致的各类问题时,例如卡音,冻屏,甚至是modem assert,可以先查看kernel log是否有发现连续大量调用printk打印太多log,此时,很有可能是因为客...

printk和printf的区别

大部分常用的C库函数在Linux内核中都已经得到了实现。在所有没有实现的函数中,最著名的就数printf()函数了。内核代码虽然无法调用 printf()函数,但它可以调用printk()函数。pri...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用printk进行内核调试的方法
举报原因:
原因补充:

(最多只允许输入30个字)