Linux kernel panic 问题解决方案

来源:互联网 发布:java对4取整 编辑:程序博客网 时间:2024/05/18 01:58

=====================================================

arm linux系统启动相关文章列表:
arm linux系统启动流程 http://blog.csdn.net/u010872301/article/details/72615117
分析arm linux启动打印信息 http://blog.csdn.net/u010872301/article/details/78779503
Linux kernel panic 问题解决方案 http://blog.csdn.net/u010872301/article/details/73928935

=====================================================

kernel panic错误表现

kernel panic 主要有以下几个出错提示:
(1)Kernel panic-not syncing fatal exception in interrupt
(2)kernel panic - not syncing: Attempted to kill the idle task!
(3)kernel panic - not syncing: killing interrupt handler!
(4)Kernel Panic - not syncingAttempted to kill init !

kernel错误分析

查看了一下 Linux的源码文件,找到相关位置

kernel/panic.cNORET_TYPE void panic(const char * fmt, ...){static char buf[1024];va_list args;bust_spinlocks(1);va_start(args, fmt);vsnprintf(buf, sizeof(buf), fmt, args);va_end(args);printk(KERN_EMERG "Kernel panic - not syncing: %s/n",buf);bust_spinlocks(0);kernel/exit.cif (unlikely(in_interrupt()))panic("Aiee, killing interrupt handler!"); #中断处理if (unlikely(!tsk->pid))panic("Attempted to kill the idle task!"); #空任务if (unlikely(tsk->pid == 1))panic("Attempted to kill init!"); #初始化

从其他源文件和相关文档看到应该有几种原因:

1、硬件问题
使用了 SCSI-device 并且使用了未知命令
#WDIOS_TEMPPANIC Kernel panic on temperature trip# # The SETOPTIONS call can be used to enable and disable the card# and to ask the driver to call panic if the system overheats.# # If one uses a SCSI-device of unsupported type/commands, one# immediately runs into a kernel-panic caused by Command Error. To better# understand which SCSI-command caused the problem, I extended this# specific panic-message slightly.# #read/write causes a command error from# the subsystem and this causes kernel-panic

2、系统过热
如果系统过热会调用panci,系统挂起
#WDIOS_TEMPPANIC Kernel panic on temperature trip# # The SETOPTIONS call can be used to enable and disable the card# and to ask the driver to call panic if the system overheats.
3、文件系统引起
#A variety of panics and hangs with /tmp on a reiserfs filesystem#Any other panic, hang, or strange behavior## It turns out that there's a limit of six environment variables on the# kernel command line. When that limit is reached or exceeded, argument# processing stops, which means that the 'root=' argument that UML# usually adds is not seen. So, the filesystem has no idea what the# root device is, so it panics.# The fix is to put less stuff on the command line. Glomming all your# setup variables into one is probably the best way to Go.
linux内核命令行有6个环境变量。如果即将达到或者已经超过了的话 root= 参数会没有传进去
启动时会引发panics错误。
vi grub.conf#####################title Red Hat Enterprise Linux AS (2.6.9-67.0.15.ELsmp)root (hd0,0)kernel /boot/vmlinuz-2.6.9-67.0.15.ELsmp ro root=LABEL=/initrd /boot/initrd-2.6.9-67.0.15.ELsmp.imgtitle Red Hat Enterprise Linux AS-up (2.6.9-67.EL)root (hd0,0)kernel /boot/vmlinuz-2.6.9-67.EL ro root=LABEL=/initrd /boot/initrd-2.6.9-67.EL.img
应该是 其中的 root=LABEL=/ 没有起作用。
4、内核更新
网上相关文档多半是因为升级内核引起的,建议使用官方标准版、稳定版
另外还有使用磁盘的lvm 逻辑卷,添加CPU和内存。可在BIOS中禁掉声卡驱动等不必要的设备。

也有报是ext3文件系统的问题。
解决: 手工编译内核,把 ext3相关的模块都编译进去,

5、处理panic后的系统自动重启
panic.c源文件有个方法,当panic挂起后,指定超时时间,可以重新启动机器

if (panic_timeout > 0){int i;/** Delay timeout seconds before rebooting the machine.* We can't use the "normal" timers since we just panicked..*/printk(KERN_EMERG "Rebooting in %d seconds..",panic_timeout);for (i = 0; i < panic_timeout; i++) {touch_nmi_watchdog();mdelay(1000);}


修改方法:
/etc/sysctl.conf文件中加入
kernel.panic = 30 #panic错误中自动重启,等待时间为30秒
kernel.sysrq=1 #激活Magic SysRq! 否则,键盘鼠标没有响应

Linux Kernel Panic之后的招数

Linux的稳定性勿容置疑,但是有些时候一些Kernel的致命错误还是会发生(有些时候甚至是因为硬件的原因或驱动故障),Kernel Panic会导致系统crash,并且默认的系统会一直hung在那里,直到你去把它重新启动!
不过你可以在/etc/sysctl.conf文件中加入
kernel.panic = 20
来告诉系统从Panic错误中自动重启,等待时间为20秒!这个由管理员自己设定!
另外一个讨厌的事情是系统hung住之后,键盘鼠标没有响应,这个可以通过设置Magic SysRq来试着解决,也是在/etc/sysctl.conf中,
kernel.sysrq=1
来激活Magic SysRq!
这样在挂住的时候至少还有一招可以使,
按住 [ALT]+[SysRq]+[COMMAND], 这里SysRq是Print SCR键,而COMMAND按以下来解释!b - 立即重启
e - 发送SIGTERM给init之外的系统进程
o - 关机
s - sync同步所有的文件系统
u - 试图重新挂载文件系统
当然,谁也不希望经常用到这些招数!:O,有备无患而已

Kernel panic问题如何调试

Linux kernel panic是很难定位和排查的重大故障,一旦系统发生了kernel panic,相关的日志信息非常少,而一种常见的排查方法—重现法–又很难实现,因此遇到kernel panic的问题,一般比较头疼。

没有一个万能和完美的方法来解决所有的kernel panic问题,这篇文章仅仅只是给出一些思路,一来如何解决kernel panic的问题,二来可以尽可能减少发生kernel panic的机会。

什么是kernel panic

就像名字所暗示的那样,它表示Linux kernel走到了一个不知道该怎么走下一步的状况,一旦到这个情况,kernel就尽可能把它此时能获取的全部信息都打印出来,至于能打印出多少信息,那就看是那种情况导致它panic了。

有两种主要类型kernel panic:

1.hard panic(也就是Aieee信息输出)
2.soft panic (也就是Oops信息输出)
什么能导致kernel panic

只有加载到内核空间的驱动模块才能直接导致kernel panic,你可以在系统正常的情况下,使用lsmod查看当前系统加载了哪些模块。
除此之外,内建在内核里的组件(比如memory map等)也能导致panic。

因为hard panic和soft panic本质上不同,因此我们分别讨论。

如何排查hard panic

一般出现下面的情况,就认为是发生了kernel panic:

  1. 机器彻底被锁定,不能使用
  2. 数字键(Num Lock),大写锁定键(Caps Lock),滚动锁定键(Scroll Lock)不停闪烁。
  3. 如果在终端下,应该可以看到内核dump出来的信息(包括一段”Aieee”信息或者”Oops”信息)
  4. 和Windows蓝屏相似

原因:

对于hard panic而言,最大的可能性是驱动模块的中断处理(interrupt handler)导致的,一般是因为驱动模块在中断处理程序中访问一个空指针(null pointre)。一旦发生这种情况,驱动模块就无法处理新的中断请求,最终导致系统崩溃。

信息收集
根据panic的状态不同,内核将记录所有在系统锁定之前的信息。因为kenrel panic是一种很严重的错误,不能确定系统能记录多少信息,下面是一些需要收集的关键信息,他们非常重要,因此尽可能收集全,当然如果系统启动的时候就kernel panic,那就无法只知道能收集到多少有用的信息了。

  1. /var/log/messages: 幸运的时候,整个kernel panic栈跟踪信息都能记录在这里。
  2. 应用程序/库 日志: 可能可以从这些日志信息里能看到发生panic之前发生了什么。
  3. 其他发生panic之前的信息,或者知道如何重现panic那一刻的状态
  4. 终端屏幕dump信息,一般OS被锁定后,复制,粘贴肯定是没戏了,因此这类信息,你可以需要借助数码相机或者原始的纸笔工具了。

如果kernel dump信息既没有在/var/log/message里,也没有在屏幕上,那么尝试下面的方法来获取(当然是在还没有死机的情况下):

  1. 如果在图形界面,切换到终端界面,dump信息是不会出现在图形界面的,甚至都不会在图形模式下的虚拟终端里。
  2. 确保屏幕不黑屏,可以使用下面的几个方法:
    • setterm -blank 0
    • setterm -powerdown 0
    • setvesablank off
  3. 从终端,拷贝屏幕信息(方法见上)

完整栈跟踪信息的排查方法

栈跟踪信息(stack trace)是排查kernel panic最重要的信息,该信息如果在/var/log/messages日志里当然最好,因为可以看到全部的信息,如果仅仅只是在屏幕上,那么最上面的信息可能因为滚屏消失了,只剩下栈跟踪信息的一部分。如果你有一个完整栈跟踪信息的话,那么就可能根据这些充分的信息来定位panic的根本原因。要确认是否有一个足够的栈跟踪信息,你只要查找包含”EIP”的一行,它显示了是什么函数和模块调用时导致panic。大概就像下面这个例子一样:

EIP is at _dlgn_setevmask [streams-dlgnDriver] 0xehard panic的一个完整跟踪信息例子:Unable to handle kernel NULL pointer dereference at virtual address 0000000cprinting eip:f89e568a*pde = 32859001*pte = 00000000Oops: 0000Kernel 2.4.9-31enterpriseCPU: 1EIP: 0010:[<f89e568a>] Tainted: PFEFLAGS: 00010096EIP is at _dlgn_setevmask [streams-dlgnDriver] 0xeeax: 00000000 ebx: f65f5410 ecx: f5e16710 edx: f65f5410esi: 00001ea0 edi: f5e23c30 ebp: f65f5410 esp: f1cf7e78ds: 0018 es: 0018 ss: 0018Process pwcallmgr (pid: 10334, stackpage=f1cf7000)Stack: 00000000 c01067fa 00000086 f1cf7ec0 00001ea0 f5e23c30 f65f5410 f89e53ecf89fcd60 f5e16710 f65f5410 f65f5410 f8a54420 f1cf7ec0 f8a4d73a 0000139ef5e16710 f89fcd60 00000086 f5e16710 f5e16754 f65f5410 0000034a f894e648Call Trace: [setup_sigcontext+218/288] setup_sigcontext [kernel] 0xdaCall Trace: [<c01067fa>] setup_sigcontext [kernel] 0xda[<f89e53ec>] dlgnwput [streams-dlgnDriver] 0xe8[<f89fcd60>] Sm_Handle [streams-dlgnDriver] 0×1ea0[<f8a54420>] intdrv_lock [streams-dlgnDriver] 0×0[<f8a4d73a>] Gn_Maxpm [streams-dlgnDriver] 0×8ba[<f89fcd60>] Sm_Handle [streams-dlgnDriver] 0×1ea0[<f894e648>] lis_safe_putnext [streams] 0×168[<f8a7b098>] __insmod_streams-dvbmDriver_S.bss_L117376 [streams-dvbmDriver] 0xab8[<f8a78821>] dvbmwput [streams-dvbmDriver] 0×6f5[<f8a79f98>] dvwinit [streams-dvbmDriver] 0×2c0[<f894e648>] lis_safe_putnext [streams] 0×168[<f893e6d8>] lis_strputpmsg [streams] 0×54c[<f895482e>] __insmod_streams_S.rodata_L35552 [streams] 0×182e[<f8951227>] sys_putpmsg [streams] 0×6f[system_call+51/56] system_call [kernel] 0×33[<c010719b>] system_call [kernel] 0×33Nov 28 12:17:58 talus kernel:Nov 28 12:17:58 talus kernel:Code: 8b 70 0c 8b 06 83 f8 20 8b 54 24 20 8b 6c 24 24 76 1c 89 5c

完整栈信息无效的排查方法

如果只有部分跟踪信息,要快速定位问题的根本原因就变得很难,因为没有明显的信息来告诉我们是哪个模块或者函数的调用导致了内核panic,你可能只能看到kernel最后的一些指令。这种情况下,要尽可能多的收集信息,包括程序日志,库的跟踪信息,故障重现的步骤等。

Hard panic 部分跟踪信息例子(没有EIP信息):[<c01e42e7>] ip_rcv [kernel] 0×357[<f8a179d5>] sramintr [streams_dlgnDriver] 0×32d[<f89a3999>] lis_spin_lock_irqsave_fcn [streams] 0×7d[<f8a82fdc>] inthw_lock [streams_dlgnDriver] 0×1c[<f8a7bad8>] pwswtbl [streams_dlgnDriver] 0×0[<f8a15442>] dlgnintr [streams_dlgnDriver] 0×4b[<f8a7c30a>] Gn_Maxpm [streams_dlgnDriver] 0×7ae[<c0123bc1>] __run_timers [kernel] 0xd1[<c0108a6e>] handle_IRQ_event [kernel] 0×5e[<c0108c74>] do_IRQ [kernel] 0xa4[<c0105410>] default_idle [kernel] 0×0[<c0105410>] default_idle [kernel] 0×0[<c022fab0>] call_do_IRQ [kernel] 0×5[<c0105410>] default_idle [kernel] 0×0[<c0105410>] default_idle [kernel] 0×0[<c010543d>] default_idle [kernel] 0×2d[<c01054c2>] cpu_idle [kernel] 0×2d[<c011bb86>] __call_console_drivers [kernel] 0×4b[<c011bcfb>] call_console_drivers [kernel] 0xebCode: 8b 50 0c 85 d2 74 31 f6 42 0a 02 74 04 89 44 24 08 31 f6 0f<0> Kernel panic: Aiee, killing interrupt handler!In interrupt handler – not syncing

使用内核调试工具(kenrel debugger ,aka KDB)

如果跟踪信息只有一部分且不足以用来定位问题的根本原因时,kernel debugger(KDB)就需要请出来了。
KDB编译到内核里,panic发生时,他将内核引导到一个shell环境而不是锁定。这样,我们就可以收集一些与panic相关的信息了,这对我们定位问题的根本原因有很大的帮助。

使用KDB需要注意,内核必须是基本核心版本,比如是2.4.18,而不是2.4.18-5这样子的,因为KDB仅对基本核心有效。

如何排查soft panic

症状:

  1. 没有hard panic严重
  2. 通常导致段错误(segmentation fault)
  3. 可以看到一个oops信息,/var/log/messages里可以搜索到’Oops’
  4. 机器稍微还能用(但是收集信息后,应该重启系统)

原因:

凡是非中断处理引发的模块崩溃都将导致soft panic。在这种情况下,驱动本身会崩溃,但是还不至于让系统出现致命性失败,因为它没有锁定中断处理例程。导致hard panic的原因同样对soft panic也有用(比如在运行时访问一个空指针)

信息收集:
当soft panic发生时,内核将产生一个包含内核符号(kernel symbols)信息的dump数据,这个将记录在/var/log/messages里。为了开始排查故障,可以使用ksymoops工具来把内核符号信息转成有意义的数据。

为了生成ksymoops文件,需要:

  • 从/var/log/messages里找到的堆栈跟踪文本信息保存为一个新文件。确保删除了时间戳(timestamp),否则ksymoops会失败。
  • 运行ksymoops程序(如果没有,请安装)
  • 详细的ksymoops执行用法,可以参考ksymoops(8)手册。

案例分析:

安装linux出现“Kernel panic-not syncing fatal exception in interrupt”是由于网卡驱动原因。
解决方法:将选项“Onboard Lan”的选项“Disabled”,重启从光驱启动即可。
等安装完系统之后,再进入BIOS将“Onboard Lan”的选项给“enable”,下载相应的网卡驱动安装。
如出现以下报错:
init() r8168 … 
          … …
         … :Kernel panic: Fatal exception
r8168是网卡型号。
在BIOS中禁用网卡,从光驱启动安装系统。再从网上下载网卡驱动安装。
#tar  vjxf  r8168-8.014.00.tar.bz2
# make  clean  modules       (as root or with sudo)
      # make  install
      # depmod  -a
      # modprobe  r8168
安装好系统后reboot进入BIOS把网卡打开。
另有网友在Kernel panic出错信息中看到“alc880”,这是个声卡类型。尝试着将声卡关闭,重启系统,搞定。
安装linux系统遇到安装完成之后,无法启动系统出现Kernel panic-not syncing fatal exception。很多情况是由于板载声卡、网卡、或是cpu 超线程功能(Hyper-Threading )引起的。这类问题的解决办法就是先查看错误代码中的信息,找到错误所指向的硬件,将其禁用。系统启动后,安装好相应的驱动,再启用该硬件即可。
另外出现“Kernel Panic — not syncing: attempted to kill init”和“Kernel Panic — not syncing: attempted to kill idle task”有时把内存互相换下位置或重新插拔下可以解决问题。
----------------------
分析kernel panic比较关键的就是看三点:
1) 看pc指针的值
通常是根据指针加上偏移值跟反汇编代码对照,找到出问题的位置:
arm-histbv310-linux-addr2line 0xc004ee18 -evmlinux -f
2) 看调用栈Call Trace://堆栈回溯得到函数调用信息(动态加载LCRT机制)
Unable to handle kernel paging request at virtual address bc21840cpgd = c0004000[bc21840c] *pgd=00000000Internal error: Oops: 5 [#1] SMP ARMModules linked in: tntfs(PO) ahci_platform libahci_platform libahci xhci_plat_hcd ohci_platform ehci_platform hi_cimaxplus hi_ci hi_pmoc hi_vi hi_sci hi_keyled hi_aenc hi_venc hi_png hi_jpge hi_jpeg hi_ir hi_dbe mali_kbase kds hi_fb hi_tuner hi_mce hi_pvr hi_sync hi_aiao hi_adsp hi_cipher hi_vdec hi_vpss hi_vfmw hi_adec hi_demux hi_otp hi_tde hi_i2c hi_gpio_i2c hi_gpio hi_vou hi_hdmi hi_pq hi_pdm hi_common hi_mmz hi_mediaCPU: 1 PID: 0 Comm: swapper/1 Tainted: P           O   3.18.24_hi3798cv2x #1task: de462880 ti: de4c6000 task.ti: de4c6000PC is at scheduler_tick+0x98/0xecLR is at 0x1e1c8000pc : []    lr : [<1e1c8000>]    psr: 60030193sp : de4c7de0  ip : 00000000  fp : de4c7dfcr10: debc8478  r9 : c0087c64  r8 : de4c7ea8r7 : 00000001  r6 : 00000000  r5 : de462880  r4 : de4c6000r3 : bc217fc0  r2 : ddd51fc0  r1 : 00000000  r0 : 000061aaFlags: nZCv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment kernelControl: 10c5383d  Table: 1c4d406a  DAC: 00000015PC: 0xc004ed98:ed98  e3c33d7f e59f80c0 e3c3303f e59f40bc e5939014 e1a06004 e7987109 e0865007edb8  e1a00005 e595a44c eb19ce04 e595302c e3530000 da000021 e59a3040 e1a0100aedd8  e3a02000 e1a00005 e5933044 e12fff33 e1a00005 eb001063 f57ff05b e19630b7。。。。。。。。。ffc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000ffe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000[] (rb_next) from [] (timerqueue_del+0x48/0x80)[] (timerqueue_del) from [] (__remove_hrtimer+0x48/0xcc)[] (__remove_hrtimer) from [] (__run_hrtimer+0x7c/0x1ac)[] (__run_hrtimer) from [] (hrtimer_interrupt+0x12c/0x310)[] (hrtimer_interrupt) from [] (arch_timer_handler_phys+0x40/0x48)[] (arch_timer_handler_phys) from [] (handle_percpu_devid_irq+0xb4/0x11c)[] (handle_percpu_devid_irq) from [] (__handle_domain_irq+0x8c/0xe4)[] (__handle_domain_irq) from [] (gic_handle_irq+0x30/0x6c)[] (gic_handle_irq) from [] (__irq_svc+0x40/0x54)Exception stack(0xd836fe50 to 0xd836fe98)fe40:                                     00000001 00000000 00000007 00000039fe60: dc5b5000 00000000 00000001 bf7d4cdc 00000004 bf7d4cf0 00000000 d836ff24fe80: 00001c40 d836fe98 000007c0 bf7b0c78 600f0013 ffffffff[] (__irq_svc) from [] (ENGINE_Process+0x1c4/0x928 [hi_adsp])[] (ENGINE_Process [hi_adsp]) from [] (AOE_ProcThread_Sw+0x30/0x54 [hi_adsp])[] (AOE_ProcThread_Sw [hi_adsp]) from [] (AoEngineTask+0x74/0xd4 [hi_adsp])[] (AoEngineTask [hi_adsp]) from [] (kthread+0xd8/0xf4)[] (kthread) from [] (ret_from_fork+0x14/0x20)Code: e3520000 1a000001 ea000005 e1a02003 (e5923008) ---[ end trace 020dde7f5de8c403 ]---Kernel panic - not syncing: Fatal exception in interruptCPU0: stoppingCPU: 0 PID: 1593 Comm: video Tainted: P      D    O   3.18.24_hi3798cv2x #1[] (unwind_backtrace) from [] (show_stack+0x20/0x24)[] (show_stack) from [] (dump_stack+0x84/0x9c)[] (dump_stack) from [] (handle_IPI+0x278/0x2c0)[] (handle_IPI) from [] (gic_handle_irq+0x64/0x6c)[] (gic_handle_irq) from [] (__irq_usr+0x48/0x60)Exception stack(0xdc6d9fb0 to 0xdc6d9ff8)9fa0:                                     00000000 93f04f88 00000000 000000009fc0: 00382ddc 00000000 000145f0 00000000 00000000 00000000 b6fec000 000000009fe0: 003d0f00 beeddc88 b6f97a64 000145ec 600b0010 ffffffffCPU3: stoppingCPU: 3 PID: 0 Comm: swapper/3 Tainted: P      D    O   3.18.24_hi3798cv2x #1[] (unwind_backtrace) from [] (show_stack+0x20/0x24)[] (show_stack) from [] (dump_stack+0x84/0x9c)[] (dump_stack) from [] (handle_IPI+0x278/0x2c0)[] (handle_IPI) from [] (gic_handle_irq+0x64/0x6c)[] (gic_handle_irq) from [] (__irq_svc+0x40/0x54)Exception stack(0xde4cbf68 to 0xde4cbfb0)bf60:                   debdc300 00000000 000440aa c0026860 de4ca000 00000003bf80: c0a60274 c0a1cd28 c0a1cd74 c0a60274 00000000 de4cbfbc de4cbfc0 de4cbfb0bfa0: c0016684 c0016688 600f0013 ffffffff[] (__irq_svc) from [] (arch_cpu_idle+0x40/0x4c)[] (arch_cpu_idle) from [] (cpu_startup_entry+0x15c/0x200)[] (cpu_startup_entry) from [] (secondary_start_kernel+0x11c/0x13c)[] (secondary_start_kernel) from [<00008784>] (0x8784)CPU2: stoppingCPU: 2 PID: 0 Comm: swapper/2 Tainted: P      D    O   3.18.24_hi3798cv2x #1[] (unwind_backtrace) from [] (show_stack+0x20/0x24)[] (show_stack) from [] (dump_stack+0x84/0x9c)[] (dump_stack) from [] (handle_IPI+0x278/0x2c0)[] (handle_IPI) from [] (gic_handle_irq+0x64/0x6c)[] (gic_handle_irq) from [] (__irq_svc+0x40/0x54)Exception stack(0xde4c9f68 to 0xde4c9fb0)9f60:                   debd2300 00000000 0009abb8 c0026860 de4c8000 000000029f80: c0a60274 c0a1cd28 c0a1cd74 c0a60274 00000000 de4c9fbc de4c9fc0 de4c9fb09fa0: c0016684 c0016688 600f0013 ffffffff[] (__irq_svc) from [] (arch_cpu_idle+0x40/0x4c)[] (arch_cpu_idle) from [] (cpu_startup_entry+0x15c/0x200)[] (cpu_startup_entry) from [] (secondary_start_kernel+0x11c/0x13c)[] (secondary_start_kernel) from [<00008784>] (0x8784)---[ end Kernel panic - not syncing: Fatal exception in interrupt

参考博客

Linux kernel panic问题解决方法

http://blog.csdn.net/willand1981/article/details/5663356


原创粉丝点击