现在的位置: 首页 > 综合 > 正文

linux内核调试

2014年11月13日 ⁄ 综合 ⁄ 共 2597字 ⁄ 字号 评论关闭

#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    */

extern int console_printk[];

#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(<n>"……"),只有n小于console_loglevel时才能被打印。
    假设default_message_loglevel的值等于4,如果printk的参数头没有 <n> 样式的字符,则在printk函数进一步处理前会加上<4>
    minimum_console_loglevel是一个预设的值,平时不起作用,通过其他工具来设置console_loglevel的值,这个值不能小于minimum_console_loglevel的值
    default_console_loglevel也是一个预设的值,平时不起作用,它别哦死设置console_loglevel时的默认值,通过其他工具设置console_loglevel的值时,会用到这个值

上面代码中的console_printk是一个数组,他在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函数的记录级别
挂载proc文件系统后,读取/proc/sys/kernel/printk文件可以得到console_loglevel、default_message_loglevel、minimum_console_loglevel、default_console_loglevel 这四个值。
cat /proc/sys/kernel/printk
7 4 1 7
我们可以通过下列命令来修改这个值
echo "1 4 1 7" > /proc/sys/kernel/printk

这样可以设置答应终端的答应级别,只有当printk(<n>……)中n小于console_loglevel时才能打印,如上吧console_loglevel设置为1就只有打印级别为0的printk语句才能打印出来。由于新优先级可以指定为1~8之间的整数值,所以如果我们要让所有的打印语句都能够答应出来的话我们可以
echo "8 4 1 7" > /proc/sys/kernel/printk
这样任何printk打印语句都能够打印信息。

还可以通过dmesg查看系统信息


oops消息
大部分错误都是因为对NULL指针取值或因为使用了其他不正确的指针值,这些错误通常会导致一个oops信息。
由于处理器使用的地址几乎都是虚拟地址,这些地址(除了内存管理子系统本身所使用的物理内存外)通过一个复杂的被称为页表的结构映射为物理地址,当引用一个非法指针时,分页机制无法将该地址映射为物理地址,此时处理器就会想操作系统发出一个信号,而这时处理器恰好处于超级用户模式,系统就会产生一个oops
oops显示出错时处理器的状态,比如cpu寄存器的内容以及其他看上去无法理解的信息。这些信息有printk打印出来
下面使用各使用NULL指针而导致oops的例子
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 805 [#1]
Modules linked in:
CPU: 0    Not tainted (2.6.22.6 #18)
PC is at s3c2410fb_probe+0x18/0x560
LR is at platform_drv_probe+0x20/0x24
pc : [<c001abc4>]    lr : [<c0185f28>]    psr: a0000013
sp : c042fe64 ip : c042fea0 fp : c042fe9c
r10: 00000000 r9 : c0025864 r8 : c03892ec
r7 : 00000000 r6 : c0353358 r5 : 00000000 r4 : c032c560
r3 : 00001234 r2 : 00000001 r1 : c047bd84 r0 : c032c558
Unable to handle kernel NULL pointer dereference at virtual address 00000000
可以看出使用了空指针。找出函数调用关系:PC is at s3c2410fb_probe+0x18/0x560
,表示出错指令为 s3c2410fb_probe函数中偏移为0X18的指令。pc : [<c001abc4>] 表示出错指令的地址为c001abc4

抱歉!评论已关闭.