kernel panic錯誤表現(xiàn)
kernel panic?主要有以下幾個出錯提示:
Kernel panic-not syncing fatal exception in interrupt
kernel panic - not syncing: Attempted to kill the idle task!
kernel panic - not syncing: killing interrupt handler!
Kernel Panic - not syncing:Attempted to kill init !
kernel錯誤分析
查看了一下?linux的源碼文件,找到相關(guān)位置
kernel/panic.c
NORET_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.c
if (unlikely(in_interrupt()))
panic(“Aiee, killing interrupt handler!”); #中斷處理
if (unlikely(!tsk->pid))
panic(“Attempted to kill the idle task!”); #空任務(wù)
if (unlikely(tsk->pid == 1))
panic(“Attempted to kill init!”); #初始化
從其他源文件和相關(guān)文檔看到應(yīng)該有幾種原因:
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、系統(tǒng)過熱
如果系統(tǒng)過熱會調(diào)用panci,系統(tǒng)掛起
#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、文件系統(tǒng)引起
#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內(nèi)核命令行有6個環(huán)境變量。如果即將達到或者已經(jīng)超過了的話?root=?參數(shù)會沒有傳進去
啟動時會引發(fā)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.img
title 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
應(yīng)該是?其中的?root=LABEL=/?沒有起作用。
4、內(nèi)核更新
網(wǎng)上相關(guān)文檔多半是因為升級內(nèi)核引起的,建議使用官方標(biāo)準(zhǔn)版、穩(wěn)定版
另外還有使用磁盤的lvm?邏輯卷,添加CPU和內(nèi)存。可在BIOS中禁掉聲卡驅(qū)動等不必要的設(shè)備。
也有報是ext3文件系統(tǒng)的問題。
解決:?手工編譯內(nèi)核,把?ext3相關(guān)的模塊都編譯進去,
5、處理panic后的系統(tǒng)自動重啟
panic.c源文件有個方法,當(dāng)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!?否則,鍵盤鼠標(biāo)沒有響應(yīng)
Linux Kernel Panic之后的招數(shù)
Linux的穩(wěn)定性勿容置疑,但是有些時候一些Kernel的致命錯誤還是會發(fā)生(有些時候甚至是因為硬件的原因或驅(qū)動故障),Kernel Panic會導(dǎo)致系統(tǒng)crash,并且默認(rèn)的系統(tǒng)會一直hung在那里,直到你去把它重新啟動!
不過你可以在/etc/sysctl.conf文件中加入
kernel.panic = 20
來告訴系統(tǒng)從Panic錯誤中自動重啟,等待時間為20秒!這個由管理員自己設(shè)定!
另外一個討厭的事情是系統(tǒng)hung住之后,鍵盤鼠標(biāo)沒有響應(yīng),這個可以通過設(shè)置Magic SysRq來試著解決,也是在/etc/sysctl.conf中,
kernel.sysrq=1
來激活Magic SysRq!
這樣在掛住的時候至少還有一招可以使,
按住?[ALT]+[SysRq]+[COMMAND],?這里SysRq是Print SCR鍵,而COMMAND按以下來解釋!b -?立即重啟
e -?發(fā)送SIGTERM給init之外的系統(tǒng)進程
o -?關(guān)機
s - sync同步所有的文件系統(tǒng)
u -?試圖重新掛載文件系統(tǒng)
當(dāng)然,誰也不希望經(jīng)常用到這些招數(shù)!:O,有備無患而已
Kernel?panic問題如何調(diào)試
Linux kernel panic是很難定位和排查的重大故障,一旦系統(tǒng)發(fā)生了kernel panic,相關(guān)的日志信息非常少,而一種常見的排查方法—重現(xiàn)法–又很難實現(xiàn),因此遇到kernel panic的問題,一般比較頭疼。
沒有一個萬能和完美的方法來解決所有的kernel panic問題,這篇文章僅僅只是給出一些思路,一來如何解決kernel panic的問題,二來可以盡可能減少發(fā)生kernel panic的機會。
什么是kernel panic
就像名字所暗示的那樣,它表示Linux kernel走到了一個不知道該怎么走下一步的狀況,一旦到這個情況,kernel就盡可能把它此時能獲取的全部信息都打印出來,至于能打印出多少信息,那就看是那種情況導(dǎo)致它panic了。
有兩種主要類型kernel panic:
1.hard panic(也就是Aieee信息輸出)
2.soft panic (也就是Oops信息輸出)
什么能導(dǎo)致kernel panic
只有加載到內(nèi)核空間的驅(qū)動模塊才能直接導(dǎo)致kernel panic,你可以在系統(tǒng)正常的情況下,使用lsmod查看當(dāng)前系統(tǒng)加載了哪些模塊。
除此之外,內(nèi)建在內(nèi)核里的組件(比如memory map等)也能導(dǎo)致panic。
因為hard panic和soft panic本質(zhì)上不同,因此我們分別討論。
如何排查hard panic
一般出現(xiàn)下面的情況,就認(rèn)為是發(fā)生了kernel panic:
機器徹底被鎖定,不能使用
數(shù)字鍵(Num Lock),大寫鎖定鍵(Caps Lock),滾動鎖定鍵(Scroll Lock)不停閃爍。
如果在終端下,應(yīng)該可以看到內(nèi)核dump出來的信息(包括一段”Aieee”信息或者”O(jiān)ops”信息)
和Windows藍屏相似
原因:
對于hard panic而言,最大的可能性是驅(qū)動模塊的中斷處理(interrupt handler)導(dǎo)致的,一般是因為驅(qū)動模塊在中斷處理程序中訪問一個空指針(null pointre)。一旦發(fā)生這種情況,驅(qū)動模塊就無法處理新的中斷請求,最終導(dǎo)致系統(tǒng)崩潰。
信息收集
根據(jù)panic的狀態(tài)不同,內(nèi)核將記錄所有在系統(tǒng)鎖定之前的信息。因為kenrel panic是一種很嚴(yán)重的錯誤,不能確定系統(tǒng)能記錄多少信息,下面是一些需要收集的關(guān)鍵信息,他們非常重要,因此盡可能收集全,當(dāng)然如果系統(tǒng)啟動的時候就kernel panic,那就無法只知道能收集到多少有用的信息了。
/var/log/messages:?幸運的時候,整個kernel panic棧跟蹤信息都能記錄在這里。
應(yīng)用程序/庫?日志:?可能可以從這些日志信息里能看到發(fā)生panic之前發(fā)生了什么。
其他發(fā)生panic之前的信息,或者知道如何重現(xiàn)panic那一刻的狀態(tài)
終端屏幕dump信息,一般OS被鎖定后,復(fù)制,粘貼肯定是沒戲了,因此這類信息,你可以需要借助數(shù)碼相機或者原始的紙筆工具了。
如果kernel dump信息既沒有在/var/log/message里,也沒有在屏幕上,那么嘗試下面的方法來獲取(當(dāng)然是在還沒有死機的情況下):
如果在圖形界面,切換到終端界面,dump信息是不會出現(xiàn)在圖形界面的,甚至都不會在圖形模式下的虛擬終端里。
確保屏幕不黑屏,可以使用下面的幾個方法:
setterm -blank 0
setterm -powerdown 0
setvesablank off
從終端,拷貝屏幕信息(方法見上)
完整棧跟蹤信息的排查方法
棧跟蹤信息(stack trace)是排查kernel panic最重要的信息,該信息如果在/var/log/messages日志里當(dāng)然最好,因為可以看到全部的信息,如果僅僅只是在屏幕上,那么最上面的信息可能因為滾屏消失了,只剩下棧跟蹤信息的一部分。如果你有一個完整棧跟蹤信息的話,那么就可能根據(jù)這些充分的信息來定位panic的根本原因。要確認(rèn)是否有一個足夠的棧跟蹤信息,你只要查找包含”EIP”的一行,它顯示了是什么函數(shù)和模塊調(diào)用時導(dǎo)致panic。大概就像下面這個例子一樣:
EIP is at _dlgn_setevmask [streams-dlgnDriver] 0xe
hard panic的一個完整跟蹤信息例子:
Unable to handle kernel NULL pointer dereference at virtual address 0000000c
printing eip:
f89e568a
*pde = 32859001
*pte = 00000000
Oops: 0000
Kernel 2.4.9-31enterprise
CPU: 1
EIP: 0010:[] Tainted: PF
EFLAGS: 00010096
EIP is at _dlgn_setevmask [streams-dlgnDriver] 0xe
eax: 00000000 ebx: f65f5410 ecx: f5e16710 edx: f65f5410
esi: 00001ea0 edi: f5e23c30 ebp: f65f5410 esp: f1cf7e78
ds: 0018 es: 0018 ss: 0018
Process pwcallmgr (pid: 10334, stackpage=f1cf7000)
Stack: 00000000 c01067fa 00000086 f1cf7ec0 00001ea0 f5e23c30 f65f5410 f89e53ec
f89fcd60 f5e16710 f65f5410 f65f5410 f8a54420 f1cf7ec0 f8a4d73a 0000139e
f5e16710 f89fcd60 00000086 f5e16710 f5e16754 f65f5410 0000034a f894e648
Call Trace: [setup_sigcontext+218/288] setup_sigcontext [kernel] 0xda
Call Trace: [] setup_sigcontext [kernel] 0xda
[] dlgnwput [streams-dlgnDriver] 0xe8
[] Sm_Handle [streams-dlgnDriver] 0×1ea0
[] intdrv_lock [streams-dlgnDriver] 0×0
[] Gn_Maxpm [streams-dlgnDriver] 0×8ba
[] Sm_Handle [streams-dlgnDriver] 0×1ea0
[] lis_safe_putnext [streams] 0×168
[] __insmod_streams-dvbmDriver_S.bss_L117376 [streams-dvbmDriver] 0xab8
[] dvbmwput [streams-dvbmDriver] 0×6f5
[] dvwinit [streams-dvbmDriver] 0×2c0
[] lis_safe_putnext [streams] 0×168
[] lis_strputpmsg [streams] 0×54c
[] __insmod_streams_S.rodata_L35552 [streams] 0×182e
[] sys_putpmsg [streams] 0×6f
[system_call+51/56] system_call [kernel] 0×33
[] system_call [kernel] 0×33
Nov 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
完整棧信息無效的排查方法
如果只有部分跟蹤信息,要快速定位問題的根本原因就變得很難,因為沒有明顯的信息來告訴我們是哪個模塊或者函數(shù)的調(diào)用導(dǎo)致了內(nèi)核panic,你可能只能看到kernel最后的一些指令。這種情況下,要盡可能多的收集信息,包括程序日志,庫的跟蹤信息,故障重現(xiàn)的步驟等。
Hard panic?部分跟蹤信息例子(沒有EIP信息):
[] ip_rcv [kernel] 0×357
[] sramintr [streams_dlgnDriver] 0×32d
[] lis_spin_lock_irqsave_fcn [streams] 0×7d
[] inthw_lock [streams_dlgnDriver] 0×1c
[] pwswtbl [streams_dlgnDriver] 0×0
[] dlgnintr [streams_dlgnDriver] 0×4b
[] Gn_Maxpm [streams_dlgnDriver] 0×7ae
[] __run_timers [kernel] 0xd1
[] handle_IRQ_event [kernel] 0×5e
[] do_IRQ [kernel] 0xa4
[] default_idle [kernel] 0×0
[] default_idle [kernel] 0×0
[] call_do_IRQ [kernel] 0×5
[] default_idle [kernel] 0×0
[] default_idle [kernel] 0×0
[] default_idle [kernel] 0×2d
[] cpu_idle [kernel] 0×2d
[] __call_console_drivers [kernel] 0×4b
[] call_console_drivers [kernel] 0xeb
Code: 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
使用內(nèi)核調(diào)試工具(kenrel debugger ,aka KDB)
如果跟蹤信息只有一部分且不足以用來定位問題的根本原因時,kernel debugger(KDB)就需要請出來了。
KDB編譯到內(nèi)核里,panic發(fā)生時,他將內(nèi)核引導(dǎo)到一個shell環(huán)境而不是鎖定。這樣,我們就可以收集一些與panic相關(guān)的信息了,這對我們定位問題的根本原因有很大的幫助。
使用KDB需要注意,內(nèi)核必須是基本核心版本,比如是2.4.18,而不是2.4.18-5這樣子的,因為KDB僅對基本核心有效。
如何排查soft panic
癥狀:
沒有hard panic嚴(yán)重
通常導(dǎo)致段錯誤(segmentation fault)
可以看到一個oops信息,/var/log/messages里可以搜索到’Oops’
機器稍微還能用(但是收集信息后,應(yīng)該重啟系統(tǒng))
原因:
凡是非中斷處理引發(fā)的模塊崩潰都將導(dǎo)致soft panic。在這種情況下,驅(qū)動本身會崩潰,但是還不至于讓系統(tǒng)出現(xiàn)致命性失敗,因為它沒有鎖定中斷處理例程。導(dǎo)致hard panic的原因同樣對soft panic也有用(比如在運行時訪問一個空指針)
信息收集:
當(dāng)soft panic發(fā)生時,內(nèi)核將產(chǎn)生一個包含內(nèi)核符號(kernel symbols)信息的dump數(shù)據(jù),這個將記錄在/var/log/messages里。為了開始排查故障,可以使用ksymoops工具來把內(nèi)核符號信息轉(zhuǎn)成有意義的數(shù)據(jù)。
為了生成ksymoops文件,需要:
從/var/log/messages里找到的堆棧跟蹤文本信息保存為一個新文件。確保刪除了時間戳(timestamp),否則ksymoops會失敗。
運行ksymoops程序(如果沒有,請安裝)
詳細的ksymoops執(zhí)行用法,可以參考ksymoops(8)手冊。
下面是一個soft panic的oopsg跟蹤例子:
Code: 8b 70 0c 50 e8 69 f9 f8 ff 83 c4 10 83 f8 08 74 35 66 c7 47
EIP; f89ba71e <[streams-dlgnDriver]_dlgn_setidlestate+1e/8c>
Trace; f8951bd6 <[streams]lis_wakeup_close+86/110>
Trace; f8a2705c <[streams-dlgnDriver]__module_parm_r4_feature+280/1453>
Trace; f8a27040 <[streams-dlgnDriver]__module_parm_r4_feature+264/1453>
Trace; f89b9198 <[streams-dlgnDriver]dlgnwput+e8/204>
案例分析
Kernel Panic – not syncing: attempted to kill idle task
出現(xiàn)這種錯誤是進入不了操作系統(tǒng)的,kernel panic的成因有多種多樣,但這種情況是比較奇特的一種,因為它很可能不是軟件的問題,而是硬件的問題。幾年前我用帶奔三的舊主板時遇到過,當(dāng)時不知道如何解決,只知道它偶爾出現(xiàn),放一放也會自行消失,所以當(dāng)初沒有重視。現(xiàn)在,當(dāng)我重新用上舊主板,這種情況又出現(xiàn)了,而且這一次比較頑固,無論怎樣重啟,總是這條錯誤,不但硬盤上現(xiàn)有的兩個操作系統(tǒng)都進不去,而且連光驅(qū)里的LiveCD也進不去了,這顯然不是硬盤的問題,也不是內(nèi)核的問題。以前我就明白應(yīng)該是主板的問題,可能是主板太舊,電路信號不太通暢的原因,但不知道怎么辦,害得我一天一宿沒上網(wǎng)。今天早上去網(wǎng)吧,查了點資料,大體上有幾種說法:
一種是在grub作內(nèi)核引導(dǎo)時添加idle參數(shù),這一種是國內(nèi)網(wǎng)常見的一種說法;
第二個方法是注意一下bios中顯示的CPU或者內(nèi)存條的溫度;
第三種是重新作initrd,即mkinitrd;
第四種是在grub中啟動memtest86來測試內(nèi)存,
這幾個是外國人的論壇上說的。我回到家以后,先試了第一種,加了idle的各種參數(shù)后,毫無效果,關(guān)于第二種方法,我在bios中看到似乎硬件的溫度不是可以調(diào)節(jié)的,但我從這個思路出發(fā),考慮到,如果與內(nèi)存有關(guān),不妨把三個內(nèi)存條互換一下位置,也許有效,于是,我把我的三個SD內(nèi)存換了位置,然后開機,一切正常了。
?Kernel Panic – not syncing: attempted to kill init
這一種情況的表現(xiàn)是系統(tǒng)的極不穩(wěn)定。或者進入不了系統(tǒng),syslog停止于kernel panic;或者重啟后可以進入系統(tǒng),但不久就死機,鍵盤上的Caps-Lock與Scroll-Lock兩個燈在閃。這種錯誤與上面那個有相同的成因,解決方法也相同。
?
評論
查看更多