天天看点

kernel panic 和 kernel Oops

1. Kernel panic

内核错误(Kernel panic)是指操作系统在监测到内部的致命错误,并无法安全处理此错误时采取的动作。这个概念主要被限定在Unix以及类Unix系统中;对于MicrosoftWindows系统,等同的概念通常被称为蓝屏死机。

操作系统内核中处理Kernel panic的子程序(在AT&T派生类以及BSD类Unix中,通常为panic())通常被设计用来向控制台输出错误信息,向磁盘保存一份内核内存的转储,以便事后的调试,然后等待系统被手动重启,或自动重启。

操作系统试图读写无效或不允许的内存地址是导致内核错误的一个常见原因。内核错误也有可能在遇到硬件错误或操作系统BUG时发生。

Linux kernel panic有标志性的log打印,可以作为是否发生panic的搜索关键字:

Kernel panic - not syncing: Fatal exception

2. Oops

对于Linux内核来说,Oops就意外着内核出了异常,此时会将产生异常时CPU的状态,出错的指令地址、数据地址及其他寄存器,函数调用的顺序甚至是栈里面的内容都打印出来,然后根据异常的严重程度来决定下一步的操作:杀死导致异常的进程或者挂起系统。

最典型的异常是在内核态引用了一个非法地址,通常是未初始化的野指针Null,这将导致页表异常,最终引发Oops。

linux系统足够健壮,能够正常的反应各种异常。异常通常导致当前进程的死亡,而系统依然能够继续运转,但是这种运转都处在一种不稳定的状态,随时可能出问题。对于中断上下文的异常及系统关键资源的破坏,通常会导致内核挂起,不再响应任何事件。

3. 内核的异常级别

3.1 Bug

Bug是指那些不符合内核的正常设计,但内核能够检测出来并且对系统运行不会产生影响的问题,比如在原子上下文中休眠。

3.2 Oops

程序在内核态时,进入一种异常情况,比如引用非法指针导致的数据异常,数组越界导致的取指异常,此时异常处理机制能够捕获此异常,并将系统关键信息打印到串口上,正常情况下Oops消息会被记录到系统日志中去。

Oops发生时,进程处在内核态,很可能正在访问系统关键资源,并且获取了一些锁,当进程由于Oops异常退出时,无法释放已经获取的资源,导致其他需要获取此资源的进程挂起,对系统的正常运行造成影响。通常这种情况,系统处在不稳定的状态,很可能崩溃。

3.3 Panic

当Oops发生在中断上下文中或者在进程0和1中 ,系统将彻底挂起(重启),因为中断服务程序异常后,将无法恢复,这种情况即称为内核panic。另外当系统设置了panic标志时,无论Oops发生在中断上下文还是进程上下文,都将导致内核Panic。由于在中断复位程序中panic后,系统将不再进行调度,Syslogd将不会再运行,因此这种情况下,Oops的消息仅仅打印到串口上,不会被记录在系统日志中。

4. 总结:

kernel panic一般会造成系统重启,而Oops不一定会引起系统重启,只是杀死相关进程。

  • 非中断上下文的oops只是oops;
  • 中断上下文oops要panic;
  • 如果设置了panic_on_oops,任何oops都是panic。

继续阅读