有时调试内核模块,打印信息太多了,可以通过修改/proc/sys/kernel/printk文件内容来控制。默认设置是6 4 1 7
# cat /proc/sys/kernel/printk
7 4 1 7
该文件有四个数字值,它们根据日志记录消息的重要性,定义将其发送到何处。关于不同日志级别的更多信息,请查阅syslog(2)联机帮助。上面显示的4个数据分别对应:
控制台日志级别:优先级高于该值的消息将被打印至控制台
默认的消息日志级别:将用该优先级来打印没有优先级的消息
最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级)
默认的控制台日志级别:控制台日志级别的缺省值
数值越小,优先级越高
其实这四个值是在kernel/printk.c 中被定义的,如下:
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 */
};
内核通过printk() 输出的信息具有日志级别,日志级别是通过在printk() 输出的字符串前加一个带尖括号的整数来控制的,如printk("<6>Hello, world!\n");。内核中共提供了八种不同的日志级别,在 linux/kernel.h 中有相应的宏对应。
#define KERN_EMERG "<0>" /* systemis unusable */
#define KERN_ALERT "<1>" /* actionmust be taken immediately */
#define KERN_CRIT "<2>" /*critical conditions */
#define KERN_ERR "<3>" /* errorconditions */
#define KERN_WARNING "<4>" /* warning conditions */
#define KERN_NOTICE "<5>" /* normalbut significant */
#define KERN_INFO "<6>" /*informational */
#define KERN_DEBUG "<7>" /*debug-level messages */
所以printk() 可以这样用:printk(KERN_INFO"Hello, world!\n");。
未指定日志级别的printk() 采用的默认级别是DEFAULT_MESSAGE_LOGLEVEL,这个宏在kernel/printk.c 中被定义为整数4,即对应KERN_WARNING。
如果要想在内核启动过程中打印少的信息,就可以根据自己的需要在kernel/printk.c中修改以上数值,重新编译即可!
/* printk's without a loglevel use this.. */
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
了解了上面的这些知识后,我们就应该知道如何手动控制printk打印了。例如,我想屏蔽掉所有的内核printk打印,那么我只需要把第一个数值调到最小值1或者0。
# echo 1 4 1 7 > /proc/sys/kernel/printk
或者
# echo 0 4 0 7 > /proc/sys/kernel/printk
Linux 内核配置以打印设备驱动调试信息
注: 转载请注明出处, 来自chenhui的博客:http://blog.163.com/whpt_chenhui/blog/static/1665966902011111113710540/最近学习Linux内核下IIC驱动编程,想打印调试消息,弄了半天才弄出来,和大家一起分享以下:
在网上搜了一下帖子,说得不甚清楚,我结合我的应用整理了一下.
内核在IIC驱动( ./drivers/i2c/ )的makefile有如下代码:
ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
EXTRA_CFLAGS += -DDEBUG
endif
Kconfig里面当然也有对应的:
config I2C_DEBUG_CORE bool "I2C Core debugging messages"
help Say Y here if you want the I2C core to produce a bunch of debug
messages to the system log. Select this if you are having a
problem with I2C support and want to see more of what is going on.
在配置内核时, 设置IIC对应的debug项目:
Device Drivers --->
<*> I2C support -->
<*> I2C Core debugging messages
<*> I2C Algorithm debugging messages
<*> I2C Bus debugging messages
<*> I2C Chip debugging messages
重新编译内核然. 烧写启动后更该printk的缺省值:
#echo 8 > /proc/sys/kernel/printk
后运行 ./i2c_test, 会看见如下的调试信息:
注: IIC测试程序代码:http://blog.csdn.net/hongtao_liu/article/details/4964244
i2c-adapter i2c-0: ioctl, cmd=0x702, arg=0x01
i2c-adapter i2c-0: ioctl, cmd=0x701, arg=0x02
i2c-adapter i2c-0: ioctl, cmd=0x707, arg=0xbeb95d28
i2c-adapter i2c-0: master_xfer[0] W, addr=0x50, len=2
s3c2440-i2c s3c2440-i2c: START: 000000d0 to IICSTAT, a0 to DS
s3c2440-i2c s3c2440-i2c: iiccon, 000000e0
s3c2440-i2c s3c2440-i2c: STOP
s3c2440-i2c s3c2440-i2c: master_complete 0
i2c-adapter i2c-0: ioctl, cmd=0x707, arg=0xbeb95d28
i2c-adapter i2c-0: master_xfer[0] W, addr=0x50, len=1
i2c-adapter i2c-0: master_xfer[1] R, addr=0x50, len=1
s3c2440-i2c s3c2440-i2c: START: 000000d0 to IICSTAT, a0 to DS
s3c2440-i2c s3c2440-i2c: iiccon, 000000e0
s3c2440-i2c s3c2440-i2c: WRITE: Next Message
s3c2440-i2c s3c2440-i2c: START: 00000090 to IICSTAT, a1 to DS
s3c2440-i2c s3c2440-i2c: iiccon, 000000f0
s3c2440-i2c s3c2440-i2c: READ: Send Stop
s3c2440-i2c s3c2440-i2c: STOP
s3c2440-i2c s3c2440-i2c: master_complete 0
buff[0]=58
网上也有方法,直接在IIC的i2c-core.c, i2c-dev.c, i2c-s3c2410.c中第一行直接加入
#define DEBUG 1
运行后的调试信息和上面的一样. 具体如下:
注: 以下文章来自网络:
lsf0129的空间:
http://hi.baidu.com/lsf0129/blog/item/3e242d88d7315603c8fc7a08.html
linux设备驱动调试,我们在内核中看到内核使用dev_dbg来控制输出信息,这个函数的实质是调用printk(KERN_DEBUG )来输出打印信息。要打开这个开关需要下面两步。
1、打开调试开关:你调试的文件中必然包含了<linux/device.h>,或者《linux/paltforam_device.h》,后者包含了前者,在包含此头文件之前,使用#define DEBUG 1 来打开调试开关:例如
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/module.h>
#define DEBUG 1 /*添加在驱动的程序中,而非头文件*/
#include <linux/platform_device.h>
在linux/device.h文件中:
#define dev_printk(level, dev, format, arg...) \
printk(level "%s %s: " format , dev_driver_string(dev) , (dev)->bus_id , ## arg)
#ifdef DEBUG
#define dev_dbg(dev, format, arg...) \
dev_printk(KERN_DEBUG , dev , format , ## arg)
#else
static inline int __attribute__ ((format (printf, 2, 3)))
dev_dbg(struct device * dev, const char * fmt, ...)
{
return 0;
}
#endif
但是这个打开了之后,也不能顺利的输出信息,原因是printk有默认的信息级别。
linux/kernel文件中
#define KERN_EMERG "<0>" /* system is unusable */
#define KERN_ALERT "<1>" /* action must be taken immediately */
#define KERN_CRIT "<2>" /* critical conditions */
#define KERN_ERR "<3>" /* error conditions */
#define KERN_WARNING "<4>" /* warning conditions */
#define KERN_NOTICE "<5>" /* normal but significant condition */
#define KERN_INFO "<6>" /* informational */
#define KERN_DEBUG "<7>" /* debug-level messages */
可以看到KERN_DEBUG是级别最低的。
2、修改文件kernel/printk文件
/* printk's without a loglevel use this.. */
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
/* We show everything that is MORE important than this.. */
#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
#define DEFAULT_CONSOLE_LOGLEVEL 8 /* anything MORE serious than KERN_DEBUG */
其中DEFAULT_CONSOLE_LOGLEVEL为终端console输出的最低级别,比这严重的都将输出。原来该值为7,则调试信息无法输出,修改为8则全部有输出。
3, 用echo命令
#echo 8 > /proc/sys/kernel/printk
#cat /proc/sys/kernel/printk
8 4 1 7
四个数字的含义:当前的loglevel、默认loglevel、最小允许的loglevel、引导时的默认loglevel。
在linux内核中的/kernel目录下printk.c文件中有一个函数:
CODE:
static void __call_console_drivers(unsigned long start, unsigned long end)
{ struct console *con; for (con = console_drivers; con; con = con->next) { if ((con->flags & CON_ENABLED) && con->write) con->write(con, &LOG_BUF(start), end - start); } } |
去掉如下两行重新编译内核即可:
CODE:
if ((con->flags & CON_ENABLED) && con->write)
con->write(con, &LOG_BUF(start), end - start); |
Linux内核用函数printk打印调试信息,该函数的用法与C库打印函数printf格式类似,但在内核使用。用户可在内核代码
中的某位置加入函数printk,直接把所关心的信息打打印到屏幕上或日志文件中。
函数printk根据日志级别(loglevel)对调试信息进行分类。日志级别用宏定义,展开为一个字符串,在编译时由预处理
器将它和消息文本拼接成一个字符串,因此函数printk中的日志级别和格式字符串间不能有逗号。
下面两个 printk 的例子,一个是调试信息,一个是临界信息:
printk(KERN_DEBUG "Here I am: %s:%i\n", _ _FILE_ _, _ _LINE_ _);
printk(KERN_CRIT "I'm trashed; giving up>\n", ptr);
样例:在用户空间或内核中开启及关闭打印调试消息 用户还可以在内核或用户空间应用程序定义统一的函数打印调试信
息,可在Makefile文件中打开或关闭调试函数。定义方法列出如下:
/*debug_on_off.h*/
#undef PDEBUG /* undef it, just in case */
#ifdef SCULL_DEBUG
#ifdef _ _KERNEL_ _
/* This>#define PDEBUG(fmt,args...) printk(KERN_DEBUG "scull: " fmt, ## args)
#else
/* This>#define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
#endif
#else
#define PDEBUG(fmt, args...) /* not debugging: nothing */
#endif
在文件Makefile加上下面几行:
# Comment/uncomment the following line to disable/enable debugging
DEBUG = y
# Add your debugging flag (or not) to CFLAGS
ifeq ($(DEBUG),y)
DEBFLAGS = -O -g -DSCULL_DEBUG # "-O"
else
DEBFLAGS = -O2
endif
CFLAGS += $(DEBFLAGS)
更改makefile中的DEBUG值,需要调试信息时,DEBUG = y,不需要时,DEBUG赋其它值。再用make编译即可。