新闻资讯
Group news
青岛广盛源肥业有限公司    您的位置: 首页  >  新闻资讯  >  正文

你知道Linux内核调试关键技术之一的printk?

2019年10月12日 文章来源:网络整理 热度:115℃ 作者:刘英

1、简介(基于s3c2440 linux)

内核调试技术之中,最简单的就是printk的使用了,它的用法和C语言应用程序中的printf使用类似,在应用程序中依靠的是stdio.h中的库,而在linux内核中没有这个库,所以在linux内核中,使用这个printk就要对内核的实现有一定的了解。

printf和printk的区别:printk会在开头处加上""样式的字符,N的范围是0~7,表示这个信息的级别。

当printk(""......);中的n < console_loglevel 时候,这个信息才能被打印出来。

在内核文件中Printk.c (kernel) 中初始化这个console_loglevel 的级别为7.

/* 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 7 /* anything MORE serious than KERN_DEBUG */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 */};

2、通过命令cat /proc/sys/kernel/printk查看等级配置:

# cat /proc/sys/kernel/printk
7 4 1 7

其中的 7 4 1 7,分别对应与:console_loglevel、default_message_loglevel、minimum_console_loglevel、default_console_loglevel 

3、修改等级配置:

#echo "1 4 1 7">/proc/sys/kernel/printk 改变这四个值,当被console_loglevel设置为1的时候,所有的调试信息都会被打印出来。

4、printk函数记录的名称及使用

在内核文件:Kernel.h (include\linux) 定义了0~7这8个级别的名称

#define   KERN_EMERG   "" /* system is unusable */#define KERN_ALERT "" /* action must be taken immediately */#define KERN_CRIT "" /* criTIcal condiTIons */#define KERN_ERR "" /* error condiTIons */#define KERN_WARNING "" /* warning condiTIons */#define KERN_NOTICE "" /* normal but significant condition*/#define KERN_INFO "" /* informational*/#define KERN_DEBUG "" /* debug-level messages */#define console_loglevel      (console_printk[0])#define default_message_loglevel (console_printk[1])#define minimum_console_loglevel (console_printk[2])#define default_console_loglevel (console_printk[3])

使用printk:

① printk(KERN_WARNING"there is a warning here!\n");//注意,中间没有逗号间隔。② printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

在①和②中,我们需要查看缓冲区log_buf中的数据,才能看到打印出来的信息。需要使用命令 #dmesg

1

2

3

4

5

6

7

8

9

10

11

12

#

# dmesg

Linux version 2.6.22.6 (book@book-desktop) (gcc version 3.4.5) #19 Thu Dec 8 14:06:03 CST 2016

CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177

Machine: SMDK2440

Memory policy: ECC disabled, Data cache writeback

On node 0 totalpages: 16384

DMA zone: 128 pages used for memmap

DMA zone: 0 pages reserved

DMA zone: 16256 pages, LIFO batch:3

Normal zone: 0 pages used for memmap

CPU S3C2440A (id 0x32440001)
................................

还可以使用 cat /proc/kmsg& 后台运行,实时打印出调试信息。在②中,__FILE__, __FUNCTION__, __LINE__分别对应的是那个文件,那个函数,第几行。非常实用。

1

2

3

4

5

6

7

8

9

# cat /proc/kmsg&

# ./firstdrvtest on

/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 23

/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 25

/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 27

# ./firstdrvtest off

/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 23

/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 25

/work/LinuxDrives/20.printk_debug/first_drv.c first_drv_open 27

5、串口与printk函数的关系:   

printk vprintk vscnprintf //先把输出信息放入临时BUFFER      // Copy the output into log_buf.     // 把临时BUFFER里的数据稍作处理,再写入log_buf     // 比如printk("abc")会得到"abc", 再写入log_buf     // 可以用dmesg命令把log_buf里的数据打印出来重现内核的输出信息 // 调用硬件的write函数输出 release_console_sem call_console_drivers          //从log_buf得到数据,算出打印级别 _call_console_drivers if ((msg_log_level < console_loglevel)//如果级别足够则打印 __call_console_drivers con->write //con是console_drivers链表中的项,对用具体的输出函数 在drives/serial/s3c2410.c中查看在该函数中注册一个console结构体

static void s3c24xx_serial_console_write(struct console *co, const char *s,unsigned int count){uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);}

串口输出函数,会调用s3c24xx_serial_console_putchar函数

上一篇:学习Linux操作系统中Alsa音频编程


下一篇:Linux Device Tree的基本概念

友情链接
Links