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)
等。