LINUX内核调试
-
BUG_ON and BUG
在内核调试中用来方便标记bug,提供断言并输出信息。最常用的两个是BUG()和BUG_ON()。其会引发oops,导致栈的回溯和错误信息打印
BUG()使用:
if (bad_thing) BUG();
但是常用BUG_ON()
BUG_ON(bad_thing);
-
WARN_ON
会调用dump_stack,打印堆栈信息,但不会OOPS
#define WARN_ON(condition)do{ if(unlikely(condition)!=0){ printk("Badness in %s at %s:%d/n", __FUNCTION__, __FILE__, __LINE__); dump_stack(); } }while(0)
-
dump_stack
作用:
输出当前CPU调用的call stack,它只在终端上打印寄存器上下文和函数跟踪线索
实现:
linux/lib/dump_stack.c void dump_stack(void)
-
panic
作用:
利用panic()引发更严重错误,调用panic()不但会打印错误信息而且还会挂起整个系统,个平台实现不同
实现:
linux/kernel/painc.c
-
printk
类似于printf在内核中输出相关信息,使用如下:
printk("Hello, World\n"); //未指定级别,采用默认级别输出 printk(KERN_XXXX "Hello, world");// 注意KERN_XXX后没有逗号
- printk日志级别:
kernel/printk.c #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */ /* 因此,如果未在 printk() 中指定日志级别,系统将默认采用4级 */ /* 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 */ DECLARE_WAIT_QUEUE_HEAD(log_wait); 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 */ //引导时默认的日志级别; }; /* 这4组数字可以在/proc/sys/kernel/printk中更改 */
当 printk()中指定的级别 (数值上)小于 当前控制台日志级别(前面说过,数值越小,严重性越高)时,printk 的信息(要有\n符)就会在控制台上显示。但无论当前控制台日志级别是何值,通过 dmesg 总能查看。
-
系统日志记录工具:syslog and log
syslog 用于执行系统日志记录活动,系统进程显示为 syslogd。配置文件是/etc/syslog.conf。如果在配置文件中把kern.*这一行前的#号去掉,那么printk的信息也会输出到控制台。其守护进程是syslogd。syslogd 进程从一组日志源(如 /dev/log 和 /dev/klog )中读取数据,并按照 /etc/syslog.conf 中的说明处理这些日志消息。
klog 未使用过,未知。
系统日志文件保存在 /var/log/ 目录下,比较重要的四个日志文件:messages,kern.log,syslog,debug。
kern.log,syslog:一般会记录所有级别的日志
messages:得到的是比控制台日志级别低的日志
debug:得到的级别是7的日志
-
内核八种日志级别
linux/kernel.h #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 */ #define KERN_INFO "<6>" /* informational */ #define KERN_DEBUG "<7>" /* debug-level messages */
-
current
current指针指向当前运行的进程,内核代码可以通过current来使用进程的特定信息,如:
printK(KERN_INFO "the process is comm %s pid %d uid %d \n", current->cred->uid.val, current->tgid, current->comm); //comm 当前进程执行的程序文件的基本名称