《Linux内核设计与实现》读书笔记——调试

printk()

printk()在“任何时候任何地方”都能调用,除了在终端初始化前的某些地方。

还有个early_printk(),能够比printk()还要早就能使用。

一个例子:

printk(KERN_INFO "Warp POST OK\n");

这里前面的KERN_INFO是打印级别,根据kdbg的值来确定是否需要输出。

打印级别有如下的一些:

printk()输出的内核消息被存放在一个环形缓冲区中,大小是LOG_BUF_LEN。

用户空间的守护进程klogd可以从缓冲区获取内核消息,再通过syslogd守护进程将他们保存在系统日志文件中。

 

oops

出现oops表示内核发生了比较严重的错误。

内核发布oops,包括向终端输出错误信息,输出寄存器中保存的信息并输出可供跟踪的回溯线索。

发送完oops之后内核会处于不稳定状态。

如果oops发生在idle进程(PID是0)或者init进程(PID是1),内核会陷入混乱;如果是其它的进程,内核就会杀死该进程并尝试继续运行。

 

内核调试选项配置

内核编译配置选项有很多调试相关的特性可以打开,来协助问题调试,比如:

CONFIG_PREEMPT=y
CONFIG_DEBUG_KERNEL=y
CONFIG_KALLSYMS=y
CONFIG_DEBUG_SPINLOCK_SLEEP=y

 

SysRq

SysRq是键盘上的一个标准按键。

当内核开启了SysRq功能,就可以通过SysRq按键与内核进行通信并完成一些调试工作,前提是内核还活着。

SysRq的操作:

 

内核调用

内核提供了一些函数直接输出调试信息,比如(include\asm-generic\bug.h):

#ifndef HAVE_ARCH_BUG
#define BUG() do {} while(0)
#endif
#ifndef HAVE_ARCH_BUG_ON
#define BUG_ON(condition) do { if (condition) ; } while(0)
#endif

还有:

NORET_TYPE void panic(const char * fmt, ...)
void dump_stack(void)

等。

 

猜你喜欢

转载自blog.csdn.net/jiangwei0512/article/details/106153200