新聞中心
Linux作為一款開(kāi)源的操作系統(tǒng),在用戶群體中有著廣泛的使用。但是,在使用Linux系統(tǒng)的過(guò)程中,可能會(huì)遇到各種各樣的問(wèn)題,其中就包括了一種名為”oops”的問(wèn)題。

創(chuàng)新互聯(lián)是一家企業(yè)級(jí)云計(jì)算解決方案提供商,超15年IDC數(shù)據(jù)中心運(yùn)營(yíng)經(jīng)驗(yàn)。主營(yíng)GPU顯卡服務(wù)器,站群服務(wù)器,服務(wù)器托管,海外高防服務(wù)器,大帶寬服務(wù)器,動(dòng)態(tài)撥號(hào)VPS,海外云手機(jī),海外云服務(wù)器,海外服務(wù)器租用托管等。
“Oops”是指”out of paper space”,即打印機(jī)缺紙的意思。但是,在Linux中,”oops”指的是一種內(nèi)核錯(cuò)誤。當(dāng)Linux內(nèi)核在執(zhí)行過(guò)程中出現(xiàn)錯(cuò)誤時(shí),會(huì)調(diào)用一個(gè)名為”oops”的函數(shù)來(lái)記錄錯(cuò)誤信息,以便開(kāi)發(fā)人員進(jìn)行調(diào)試和排錯(cuò)。
一般情況下,用戶不會(huì)直接遇到”oops”函數(shù)的錯(cuò)誤信息。但是,它對(duì)于Linux系統(tǒng)的正確性和穩(wěn)定性具有重要的作用。對(duì)于開(kāi)發(fā)人員來(lái)說(shuō),當(dāng)他們開(kāi)發(fā)新的驅(qū)動(dòng)程序、內(nèi)核模塊或者其他系統(tǒng)組件時(shí),可能會(huì)出現(xiàn)各種不同的錯(cuò)誤情況,而這些錯(cuò)誤情況可能會(huì)導(dǎo)致系統(tǒng)崩潰、重啟或者其他不良影響。為了解決這些問(wèn)題,開(kāi)發(fā)人員需要使用oops函數(shù)來(lái)查找問(wèn)題發(fā)生的根本原因,并且根據(jù)問(wèn)題的性質(zhì),采取相應(yīng)的措施來(lái)修復(fù)問(wèn)題。
當(dāng)Linux內(nèi)核發(fā)生錯(cuò)誤時(shí),oops函數(shù)會(huì)生成一個(gè)錯(cuò)誤報(bào)告。這個(gè)錯(cuò)誤報(bào)告包含了內(nèi)核出現(xiàn)錯(cuò)誤的原因、錯(cuò)誤描述和其他相關(guān)的信息。一般情況下,用戶可以使用dmesg命令來(lái)查看這些錯(cuò)誤報(bào)告,以便了解系統(tǒng)狀態(tài)和解決問(wèn)題。
對(duì)于開(kāi)發(fā)人員來(lái)說(shuō),oops函數(shù)的作用非常重要。當(dāng)他們?cè)陂_(kāi)發(fā)新的系統(tǒng)組件時(shí),可能會(huì)遇到各種各樣的錯(cuò)誤情況。這些錯(cuò)誤情況可能會(huì)導(dǎo)致系統(tǒng)崩潰或者其他不良影響。為了解決這些問(wèn)題,開(kāi)發(fā)人員需要使用oops函數(shù)來(lái)查找問(wèn)題發(fā)生的根本原因,并且根據(jù)問(wèn)題的性質(zhì),采取相應(yīng)的措施來(lái)修復(fù)問(wèn)題。這些措施可能包括修改內(nèi)核代碼、更新驅(qū)動(dòng)程序和內(nèi)核模塊,或者使用其他的解決方案。
在平常的日常使用過(guò)程中,用戶并不需要直接接觸oops函數(shù)。但是,當(dāng)系統(tǒng)出現(xiàn)問(wèn)題時(shí),oops函數(shù)會(huì)扮演非常重要的角色。通過(guò)oops函數(shù),開(kāi)發(fā)人員可以確定系統(tǒng)的錯(cuò)誤情況,采取相應(yīng)的措施來(lái)修復(fù)問(wèn)題。因此,oops函數(shù)對(duì)于保障Linux系統(tǒng)的穩(wěn)定性和正確性具有非常重要的作用。
在Linux操作系統(tǒng)中,oops函數(shù)的作用類似于Windows操作系統(tǒng)中的”藍(lán)屏”。當(dāng)Windows操作系統(tǒng)發(fā)生錯(cuò)誤時(shí),會(huì)出現(xiàn)藍(lán)色的屏幕,在屏幕上顯示錯(cuò)誤信息。通過(guò)這個(gè)錯(cuò)誤信息,開(kāi)發(fā)人員可以查找問(wèn)題的根本原因,然后采取相應(yīng)的措施來(lái)修復(fù)問(wèn)題。
oops函數(shù)是Linux系統(tǒng)中一個(gè)非常重要的函數(shù)。通過(guò)這個(gè)函數(shù),開(kāi)發(fā)人員可以查找系統(tǒng)中出現(xiàn)的錯(cuò)誤,然后采取相應(yīng)的措施來(lái)修復(fù)問(wèn)題。盡管普通用戶可能不會(huì)直接接觸到這個(gè)函數(shù),但是它對(duì)于保障系統(tǒng)的穩(wěn)定性和正確性具有非常重要的作用。
相關(guān)問(wèn)題拓展閱讀:
- linux 一個(gè)核 kernal panic后,其他核怎么辦
linux 一個(gè)核 kernal panic后,其他核怎么辦
1. Linux Kernel Panic的產(chǎn)生的原因
panic是英文中是驚慌的意思,Linux Kernel panic正如其名,linux kernel不知道如何走了,它會(huì)盡可能把它此時(shí)能獲取的全部信息都打印出來(lái)。
有兩種主要類型kernel panic,后面會(huì)對(duì)這兩類panic做詳細(xì)說(shuō)明:
1.hard panic(也就是Aieee信息輸出)
2.soft panic (也就是Oops信息輸出)
2. 常見(jiàn)Linux Kernel Panic報(bào)錯(cuò)內(nèi)容:
(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 syncing:Attempted to kill init !
3. 什么會(huì)導(dǎo)致Linux Kernel Panic?
只有加載到內(nèi)悶枝核空間的驅(qū)動(dòng)模塊才能直接導(dǎo)致kernel panic,你可以在系統(tǒng)正常的情況下,使用lod查看當(dāng)前系統(tǒng)加載了哪些模塊。
除此之外,內(nèi)建在內(nèi)核里的組件(比如memory map等)也能導(dǎo)致panic。
因?yàn)閔ard panic和soft panic本質(zhì)上不同,因此我們分別討論。
4. hard panic
一般出現(xiàn)下面的情況,就認(rèn)為是發(fā)生了kernel panic:
機(jī)器徹底被鎖定,不能使用
數(shù)字鍵(Num Lock),大寫(xiě)鎖定鍵(Caps Lock),滾動(dòng)鎖定鍵(Scroll Lock)不停閃爍。
如果在終端下,應(yīng)該可以看到內(nèi)核dump出來(lái)的信息(包括一段”Aieee”信息或者”O(jiān)ops”信息)
和Windows藍(lán)屏相似
4.1 原因
對(duì)于hard panic而言,更大的可能性是驅(qū)動(dòng)模塊的中斷處理(interrupt handler)導(dǎo)致的,一般是因?yàn)轵?qū)動(dòng)模塊在中斷處理程序中訪問(wèn)一個(gè)空指針(null pointre)。一旦發(fā)生這種情況,驅(qū)動(dòng)模塊就無(wú)法處理新的中斷請(qǐng)求,最終導(dǎo)致系統(tǒng)崩潰。
本人就曾遇到過(guò)這樣一個(gè)例子:在多核系統(tǒng)中,包括AP應(yīng)用遲罩?jǐn)_處理器、mcu微控制器和modem處理器等系統(tǒng)中,mcu控制器用于系統(tǒng)的低功耗控制,mcu微控制器由于某種原因超時(shí)向AP應(yīng)用處理器發(fā)送一個(gè)超時(shí)中斷,AP接受中斷后調(diào)用中斷處理函數(shù)讀取mcu的狀態(tài)寄存器,發(fā)現(xiàn)是mcu的超時(shí)中斷,就在中斷處理程序中主動(dòng)引用一個(gè)空指針,迫使AP處理器打印堆棧信息然后重啟linux系統(tǒng)。這就是一個(gè)典型的hard panic,這里不對(duì)mcu超時(shí)原因做深入的分析,只是用來(lái)說(shuō)明hard panic產(chǎn)生的機(jī)理。
3.2 信息收集
根據(jù)panic的狀態(tài)不同,內(nèi)核將記錄所有在系統(tǒng)鎖定之前的信息。因?yàn)閗enrel panic是一種很嚴(yán)重的錯(cuò)誤,不能確定系統(tǒng)能記錄多少信息,下面是一些需要收集的關(guān)鍵信息,他們非常重要,因此盡可能收集全,當(dāng)然如果系統(tǒng)啟動(dòng)的時(shí)候就kernel panic,那就無(wú)法只知道能收集到多少有用的信息了。
/var/log/messages: 幸運(yùn)的時(shí)候,整個(gè)kernel panic棧跟蹤信息都能記錄在這里,當(dāng)然對(duì)于嵌入式linux系統(tǒng),kernel panic的內(nèi)核打印信息被放到/data/dontpanic目錄下,包括兩個(gè)文件:apanic_console存放的是內(nèi)核控制臺(tái)的log,apanic_threads存放的是linux kernel發(fā)生panic時(shí)的所有內(nèi)核線程的堆棧信息。
應(yīng)用程序/庫(kù) 日志: 可能可以從這些日志信息里能看到發(fā)生panic之前發(fā)生了什么。
其他發(fā)生panic之前的信息,或者知道如何重現(xiàn)panic那一刻的狀態(tài)
終端屏幕dump信息,一般OS被鎖定后,復(fù)制,粘貼肯定是沒(méi)戲了,因此這類信息,你可以需要借助數(shù)碼相機(jī)或者原始的紙筆工具了。
如果kernel dump信息既沒(méi)有碼旦在/var/log/message里,也沒(méi)有在屏幕上,那么嘗試下面的方法來(lái)獲?。ó?dāng)然是在還沒(méi)有死機(jī)的情況下):
如果在圖形界面,切換到終端界面,dump信息是不會(huì)出現(xiàn)在圖形界面的,甚至都不會(huì)在圖形模式下的虛擬終端里。
確保屏幕不黑屏,可以使用下面的幾個(gè)方法:
setterm -blank 0
setterm -powerdown 0
setvesablank off
從終端,拷貝屏幕信息(方法見(jiàn)上)
實(shí)際上,當(dāng)內(nèi)核發(fā)生panic時(shí),linux系統(tǒng)會(huì)默認(rèn)立即重啟系統(tǒng),當(dāng)然這只是默認(rèn)情況,除非你修改了產(chǎn)生panic時(shí)重啟定時(shí)時(shí)間,這個(gè)值默認(rèn)情況下是0,即立刻重啟系統(tǒng)。所以當(dāng)panic時(shí)沒(méi)有把kernel信息導(dǎo)入文件的話,那么可能你很難再找到panic產(chǎn)生的地方。
3.3 完整棧跟蹤信息的排查方法
棧跟蹤信息(stack trace)是排查kernel panic最重要的信息,該信息如果在/var/log/messages日志里當(dāng)然更好,因?yàn)榭梢钥吹饺康男畔?,如果僅僅只是在屏幕上,那么最上面的信息可能因?yàn)闈L屏消失了,只剩下棧跟蹤信息的一部分。如果你有一個(gè)完整棧跟蹤信息的話,那么就可能根據(jù)這些充分的信息來(lái)定位panic的根本原因。要確認(rèn)是否有一個(gè)足夠的棧跟蹤信息,你只要查找包含”EIP”的一行,它顯示了是什么函數(shù)和模塊調(diào)用時(shí)導(dǎo)致panic。
使用內(nèi)核調(diào)試工具(kenrel debugger ,aka KDB)
如果跟蹤信息只有一部分且不足以用來(lái)定位問(wèn)題的根本原因時(shí),kernel debugger(KDB)就需要請(qǐng)出來(lái)了。
KDB編譯到內(nèi)核里,panic發(fā)生時(shí),他將內(nèi)核引導(dǎo)到一個(gè)shell環(huán)境而不是鎖定。這樣,我們就可以收集一些與panic相關(guān)的信息了,這對(duì)我們定位問(wèn)題的根本原因有很大的幫助。
使用KDB需要注意,內(nèi)核必須是基本核心版本,比如是2.4.18,而不是2.4.18-5這樣子的,因?yàn)镵DB僅對(duì)基本核心有效。
4. soft panic
4.1 癥狀:
沒(méi)有hard panic嚴(yán)重
通常導(dǎo)致段錯(cuò)誤(segmentation fault)
可以看到一個(gè)oops信息,/var/log/messages里可以搜索到’Oops’
機(jī)器稍微還能用(但是收集信息后,應(yīng)該重啟系統(tǒng))
4.2 原因
凡是非中斷處理引發(fā)的模塊崩潰都將導(dǎo)致soft panic。在這種情況下,驅(qū)動(dòng)本身會(huì)崩潰,但是還不至于讓系統(tǒng)出現(xiàn)致命性失敗,因?yàn)樗鼪](méi)有鎖定中斷處理例程。導(dǎo)致hard panic的原因同樣對(duì)soft panic也有用(比如在運(yùn)行時(shí)訪問(wèn)一個(gè)空指針)
4.3 信息收集
當(dāng)soft panic發(fā)生時(shí),內(nèi)核將產(chǎn)生一個(gè)包含內(nèi)核符號(hào)(kernel symbols)信息的dump數(shù)據(jù),這個(gè)將記錄在/var/log/messages里。為了開(kāi)始排查故障,可以使用ksymoops工具來(lái)把內(nèi)核符號(hào)信息轉(zhuǎn)成有意義的數(shù)據(jù)。
為了生成ksymoops文件,需要:
從/var/log/messages里找到的堆棧跟蹤文本信息保存為一個(gè)新文件。確保刪除了時(shí)間戳(timestamp),否則ksymoops會(huì)失敗。
運(yùn)行ksymoops程序(如果沒(méi)有,請(qǐng)安裝)
詳細(xì)的ksymoops執(zhí)行用法,可以參考ksymoops(8)手冊(cè)。
5. Kernel panic實(shí)例:
今天就遇到 一個(gè)客戶機(jī)器內(nèi)核報(bào)錯(cuò):“Kernel panic-not syncing fatal exception”,重啟后正常,幾個(gè)小時(shí)后出現(xiàn)同樣報(bào)錯(cuò),系統(tǒng)down了,有時(shí)重啟后可恢復(fù)有時(shí)重啟后仍然報(bào)同樣的錯(cuò)誤。
什么是fatal exception?
“致命異常(fatal exception)表示一種例外情況,這種情況要求導(dǎo)致其發(fā)生的程序關(guān)閉。通常,異常(exception)可能是任何意想不到的情況(它不僅僅包括程序錯(cuò)誤)。致命異常簡(jiǎn)單地說(shuō)就是異常不能被妥善處理以至于程序不能繼續(xù)運(yùn)行。
軟件應(yīng)用程序通過(guò)幾個(gè)不同的代碼層與操作系統(tǒng)及其他應(yīng)用程序相聯(lián)系。當(dāng)異常(exception)在某個(gè)代碼層發(fā)生時(shí),為了查找所有異常處理的代碼,各個(gè)代碼層都會(huì)將這個(gè)異常發(fā)送給下一層,這樣就能夠處理這種異常。如果在所有層都沒(méi)有這種異常處理的代碼,致命異常(fatal exception)錯(cuò)誤信息就會(huì)由操作系統(tǒng)顯示出來(lái)。這個(gè)信息可能還包含一些關(guān)于該致命異常錯(cuò)誤發(fā)生位置的秘密信息(比如在程序存儲(chǔ)范圍中的十六進(jìn)制的位置)。這些額外的信息對(duì)用戶而言沒(méi)有什么價(jià)值,但是可以幫助技術(shù)支持人員或開(kāi)發(fā)人員調(diào)試程序。
當(dāng)致命異常(fatal exception)發(fā)生時(shí),操作系統(tǒng)沒(méi)有其他的求助方式只能關(guān)閉應(yīng)用程序,并且在有些情況下是關(guān)閉操作系統(tǒng)本身。當(dāng)使用一種特殊的應(yīng)用程序時(shí),如果反復(fù)出現(xiàn)致命異常錯(cuò)誤的話,應(yīng)將這個(gè)問(wèn)題報(bào)告給軟件供應(yīng)商。 ” 而且此時(shí)鍵盤無(wú)任何反應(yīng),必然使用reset鍵硬重啟。
panic.c源文件有個(gè)方法,當(dāng)panic掛起后,指定超時(shí)時(shí)間,可以重新啟動(dòng)機(jī)器,這就是前面說(shuō)的panic超時(shí)重啟。如果你的機(jī)器事先配置好了魔法鍵的使用,就可以在超時(shí)之前通過(guò)魔法鍵使系統(tǒng)在重啟前盡可能多的為你多做些事情,當(dāng)然這些事情不是用來(lái)使系統(tǒng)恢復(fù)正常,而是盡量避免損失或?qū)С鲆恍┯杏眯畔?lái)幫助后面的定位。
方法:
#vi /etc/sysctl.conf 添加
kernel.panic = 20 #panic error中自動(dòng)重啟,等待timeout為20秒
kernel.sysrq=1 #激活Magic SysRq 否則,鍵盤鼠標(biāo)沒(méi)有響應(yīng)
按住 ++, 這里SysRq是Print SCR鍵,而COMMAND按以下來(lái)解釋!
b – 立即重啟
e – 發(fā)送SIGTERM給init之外的系統(tǒng)進(jìn)程
o – 關(guān)機(jī)
s – sync同步所有的文件系統(tǒng)
u – 試圖重新掛載文件系統(tǒng)
配置一下以防萬(wàn)一。
很多網(wǎng)友安裝linux出現(xiàn)“Kernel panic-not syncing fatal exception in interrupt”是由于網(wǎng)卡驅(qū)動(dòng)原因。解決方法:將選項(xiàng)“Onboard Lan”的選項(xiàng)“Disabled”,重啟從光驅(qū)啟動(dòng)即可。等安裝完系統(tǒng)之后,再進(jìn)入BIOS將“Onboard Lan”的選項(xiàng)給“enable”,下載相應(yīng)的網(wǎng)卡驅(qū)動(dòng)安裝。
如出現(xiàn)以下報(bào)錯(cuò):
init() r8168 …
… …
… :Kernel panic: Fatal exception
r8168是網(wǎng)卡型號(hào)。
在BIOS中禁用網(wǎng)卡,從光驅(qū)啟動(dòng)安裝系統(tǒng)。再?gòu)木W(wǎng)上下載網(wǎng)卡驅(qū)動(dòng)安裝。
#tar vjxf r8168-8.014.00.tar.bz2
# make clean modules(as root or with sudo)
# make install
# depmod -a
# modprobe r8168
安裝好系統(tǒng)后reboot進(jìn)入BIOS把網(wǎng)卡打開(kāi)。
另有網(wǎng)友在Kernel panic出錯(cuò)信息中看到“alc880”,這是個(gè)聲卡類型。嘗試著將聲卡關(guān)閉,重啟系統(tǒng),搞定。
安裝linux系統(tǒng)遇到安裝完成之后,無(wú)法啟動(dòng)系統(tǒng)出現(xiàn)Kernel panic-not syncing fatal exception。很多情況是由于板載聲卡、網(wǎng)卡、或是cpu 超線程功能(Hyper-Threading )引起的。這類問(wèn)題的解決辦法就是先查看錯(cuò)誤代碼中的信息,找到錯(cuò)誤所指向的硬件,將其禁用。系統(tǒng)啟動(dòng)后,安裝好相應(yīng)的驅(qū)動(dòng),再啟用該硬件即可。
另外出現(xiàn)“Kernel Panic — not syncing: attempted to kill init”和“Kernel Panic — not syncing: attempted to kill idle task”有時(shí)把內(nèi)存互相換下位置或重新插拔下可以解決問(wèn)題。
6. 一個(gè)kernel panic的解決之法
相信使用linux kernel開(kāi)發(fā)過(guò)驅(qū)動(dòng)的兄弟都知道,kernel panic對(duì)系統(tǒng)帶來(lái)的危害要比應(yīng)用程序panic大的多,甚至可以用災(zāi)難來(lái)形容。對(duì)于應(yīng)用程序的panic最多導(dǎo)致linux系統(tǒng)殺掉該用戶進(jìn)程,但對(duì)于kernel panic就沒(méi)辦法了,因?yàn)閗ernel是整個(gè)系統(tǒng)的管理者,自己出現(xiàn)問(wèn)題了(當(dāng)然是不可恢復(fù)的異常)就只能等待重啟了。
kernel panic的更大問(wèn)題就是難于定位,對(duì)于一個(gè)開(kāi)發(fā)者來(lái)說(shuō),有些kernel panic那簡(jiǎn)直就像是一場(chǎng)噩夢(mèng),上面主要說(shuō)明了如何抓取kernel panic的方法和一些panic實(shí)例,當(dāng)然,抓取panic的打印信息是解決panic的之一步也是關(guān)鍵一步,下面就根據(jù)自己曾碰到過(guò)的一個(gè)kernel panic做為實(shí)例來(lái)說(shuō)明從出現(xiàn)panic到解決panic的一般方法。
6.1 抓取kernel panic信息
沒(méi)錯(cuò),正如前面說(shuō)的,這是之一步也是非常關(guān)鍵的一步,如果要解決一個(gè)kernel panic當(dāng)然必須首先要知道它產(chǎn)生的地方,也就是說(shuō)產(chǎn)生panic的內(nèi)核函數(shù)調(diào)用棧,當(dāng)前的內(nèi)核調(diào)用棧記錄了產(chǎn)生kernel panic時(shí)的函數(shù)調(diào)用關(guān)系鏈,這里我不在貼出相關(guān)的打印實(shí)例,這樣的kernel panic網(wǎng)上也到處都是,而且還有很多的文章來(lái)說(shuō)明如何確定是哪個(gè)源文件的哪一行導(dǎo)致的panic,因此感興趣的同學(xué)可以搜索一些這樣的文章看看,這里指說(shuō)明一下解決kernel panic的一般步驟和注意事項(xiàng)。
對(duì)于抓取kernel log的方法前面有介紹,這里不贅述,但想強(qiáng)調(diào)兩點(diǎn):
(1) 不管是什么樣的panic,首先要抓取足夠的內(nèi)核打印信息,當(dāng)然必要的情況下還需要搜集產(chǎn)生kernel panic時(shí)的應(yīng)用程序的打印信息,對(duì)于Android系統(tǒng)來(lái)說(shuō)就是logcat信息,在android嵌入式軟件平臺(tái)上其實(shí)有更好更全面的log搜集方法,那就是bugreport,它將產(chǎn)生此刻系統(tǒng)全方位的信息,對(duì),沒(méi)錯(cuò),就是全方位的信息,包括內(nèi)核、應(yīng)用、內(nèi)存、進(jìn)程和處理器等所有相關(guān)信息,是一個(gè)非常好的調(diào)試工具,至于bugreport的工作原理感興趣的同學(xué)自己查找下資料。
注意:bugreport的使用需注意兩點(diǎn):之一,它只能在系統(tǒng)正常運(yùn)行的情況下使用,第二,正因?yàn)橹稽c(diǎn),你需要在系統(tǒng)產(chǎn)生kernel panic重啟系統(tǒng)后的之一時(shí)間使用bugreport導(dǎo)出所有信息,因?yàn)檫@所有信息中包含了上次系統(tǒng)重啟的原因的相關(guān)log信息。
(2) 既然是抓取panic log信息,必然少不了復(fù)現(xiàn)panic這個(gè)過(guò)程,有的panic的產(chǎn)生時(shí)概率性隨機(jī)的,就是說(shuō)你不知道什么時(shí)候就可能會(huì)產(chǎn)生panic,因此請(qǐng)珍惜每一次復(fù)現(xiàn)panic的機(jī)會(huì),起碼要在復(fù)現(xiàn)panic之前準(zhǔn)備好你要抓取的是那些信息,這些信息能否幫助你進(jìn)一步定位panic,否則,不要在出現(xiàn)panic時(shí)手忙腳亂,不知道自己要什么,更好每次復(fù)現(xiàn)panic前計(jì)劃好這次你要那些信息(可能每次抓取信息的重點(diǎn)不一樣)。
注意:在工作中經(jīng)常碰到這樣一個(gè)現(xiàn)象:測(cè)試部門的同學(xué)好不容易發(fā)現(xiàn)一個(gè)問(wèn)題,請(qǐng)開(kāi)發(fā)同學(xué)定位,開(kāi)發(fā)同學(xué)基本上沒(méi)怎么分析問(wèn)題就嚷著信息抓的不夠沒(méi)法定位,結(jié)果讓測(cè)試同學(xué)半天甚至一天來(lái)復(fù)現(xiàn)這個(gè)問(wèn)題,等復(fù)現(xiàn)了問(wèn)題開(kāi)發(fā)同學(xué)還沒(méi)搞清楚自己到底要什么信息來(lái)定位,有的問(wèn)題復(fù)現(xiàn)時(shí)的環(huán)境只能保持幾分鐘甚至幾十秒鐘,這勢(shì)必會(huì)浪費(fèi)了測(cè)試同學(xué)的勞動(dòng)成果。
6.2 分析kernel panic
搜集了足夠的panic信息,下面就是分析panic的時(shí)候了,對(duì)于一個(gè)panic問(wèn)題,你要知道三點(diǎn):
(1) 首先要對(duì)匯編語(yǔ)言有一定的了解,定位panic產(chǎn)生的C代碼位置
其實(shí)就是根據(jù)當(dāng)前內(nèi)核線程的內(nèi)核調(diào)用棧查找產(chǎn)生panic調(diào)用鏈,在panic log的前面幾行已經(jīng)顯示了kernel panic的代碼位置,但這個(gè)位置是相對(duì)于產(chǎn)生panic函數(shù)的偏移,你并不知道它到底是哪一行,這個(gè)時(shí)候你需要objdump反匯編器來(lái)對(duì)那個(gè)產(chǎn)生panic的鏡像文件反匯編,然后根據(jù)panic信息的指示找到對(duì)應(yīng)的匯編代碼,對(duì)照C代碼根據(jù)匯編上下文確定C代碼行,其實(shí),kernel panic的產(chǎn)生一般都是非法地址的引用,尤其是NULL指針的引用,這也比較容易定位出panic的C代碼行。
(2) 分析導(dǎo)致panic的C代碼行上下文,確定panic引入點(diǎn)
之一步應(yīng)該會(huì)比較容易找到導(dǎo)致panic 的C代碼行,根據(jù)產(chǎn)生panic的代碼進(jìn)一步找到panic的引入點(diǎn),這一步可以搭配printk來(lái)定位(如果是大概率panic就更容易定位了),這一步相對(duì)之一步花費(fèi)多一點(diǎn)的時(shí)間,如果是應(yīng)用代碼分析到這里已經(jīng)差不多結(jié)束了,確定了panic引入點(diǎn)就可以修改代碼進(jìn)行回歸測(cè)試了,但對(duì)于kernel來(lái)說(shuō)要復(fù)雜的多。
正如之前曾碰到的panic,復(fù)現(xiàn)雖然不容易但是基本上在固定時(shí)間點(diǎn)左右就可以復(fù)現(xiàn),我是用的腳本循環(huán)加載卸載wifi模塊,每次都是大約500次左右產(chǎn)生panic,要知道必現(xiàn)的panic就容易解決的多了,但當(dāng)時(shí)因?yàn)檫@500次的循環(huán)就要花費(fèi)2個(gè)小時(shí)左右,而且環(huán)境還經(jīng)常出現(xiàn)問(wèn)題,導(dǎo)致我花費(fèi)很長(zhǎng)時(shí)間才定位出問(wèn)題所在:每次的加載和卸載wifi模塊都導(dǎo)致devices kset節(jié)點(diǎn)引用計(jì)數(shù)多減一,當(dāng)devices kset的引用計(jì)數(shù)變?yōu)?的時(shí)候被系統(tǒng)回收,linux系統(tǒng)隨后可能會(huì)出現(xiàn)N種panic現(xiàn)象,之后發(fā)現(xiàn)是因?yàn)閣ifi模塊每次加載下載時(shí)對(duì)應(yīng)的設(shè)備節(jié)點(diǎn)的引用計(jì)數(shù)增減失衡導(dǎo)致devices kset被多減一,然后發(fā)現(xiàn)是linux 內(nèi)核核心代碼的問(wèn)題。
(3) 更好不要懷疑linux的核心代碼,也不要試圖去修改
正因?yàn)檫@一點(diǎn),讓我遲遲不敢確定是不是真的核心代碼問(wèn)題,linux的核心代碼那可是數(shù)以萬(wàn)計(jì)的大牛經(jīng)過(guò)千錘百煉的代碼,豈容你輕易修改,經(jīng)過(guò)進(jìn)一步的分析這個(gè)panic是因?yàn)槲覀冇玫膚ifi卡是非標(biāo)準(zhǔn)媒體卡,走的是非標(biāo)準(zhǔn)流程,在這個(gè)流程中對(duì)wifi設(shè)備初始化時(shí)少了一次wifi設(shè)備節(jié)點(diǎn)的引用,但在卸載模塊時(shí)同標(biāo)準(zhǔn)卡一樣被解引用了。
(4)不要堅(jiān)定的以為圍繞著panic信息就能解決panic問(wèn)題
還是上面的panic,實(shí)際上,上面提到的panic問(wèn)題其實(shí)應(yīng)該是很多的panic,這也是在后期復(fù)現(xiàn)panic時(shí)發(fā)現(xiàn)的,在加載卸載500次左右時(shí)必現(xiàn)panic,但卻不是同一個(gè)panic,如果按照正常思路:既然是panic,就應(yīng)該從panic信息下手,順藤摸瓜一直追下去。如果是這樣,這個(gè)問(wèn)題恐怕永遠(yuǎn)也解決不了,因?yàn)槟阍趶?fù)現(xiàn)一個(gè)panic時(shí)總是會(huì)有其他的panic出現(xiàn),這回讓你無(wú)所適從的。
通過(guò)對(duì)這些panic的log的分析,發(fā)現(xiàn)他們都有一個(gè)共性,在產(chǎn)生panic之前都有一段WARNING打印,也正是對(duì)這段打印的分析找出了問(wèn)題的根源,對(duì)于這段WARNING的內(nèi)容和分析過(guò)程不在這里說(shuō)明,只為表達(dá)下面的觀點(diǎn):
事實(shí)證明,在碰到panic問(wèn)題定位時(shí),如果想當(dāng)一段時(shí)間內(nèi)定位不出來(lái),又沒(méi)有什么更好的思路時(shí),你應(yīng)該回頭看看在panic之前kernel是否產(chǎn)生了哪些不太正常的log,這也許就是導(dǎo)致kernel panic的前兆或推手。
(5) 盡可能多的把握l(shuí)inux kernel的行為,對(duì)一些難啃的panic大膽猜測(cè)
這里的大膽猜測(cè)是建立在想當(dāng)了解linux kernel行為上的有理性的推理,盡管有些猜測(cè)并不是完全正確的,但在你證明它是正確的過(guò)程中或許會(huì)有意外收獲。對(duì)于wifi模塊加載卸載的panic問(wèn)題來(lái)說(shuō),我曾有過(guò)兩次錯(cuò)誤的猜測(cè):
之一次,因?yàn)殚L(zhǎng)時(shí)間的加載卸載都會(huì)出現(xiàn)panic,而且開(kāi)始發(fā)現(xiàn)的panic是在kmem_cache_alloc函數(shù)中,因此猜測(cè)是內(nèi)存泄露導(dǎo)致的內(nèi)存耗盡,因此在后面的復(fù)現(xiàn)過(guò)程中我寫(xiě)了個(gè)腳本循環(huán)打印內(nèi)存的使用情況,發(fā)現(xiàn)內(nèi)存的占用一直穩(wěn)定在一個(gè)正常的范圍,證明了我的之一個(gè)猜測(cè)是錯(cuò)誤的。
第二次,在看到devices 的內(nèi)核對(duì)象kobject的名字在panic之前出現(xiàn)亂碼的情況下(printk打印了名字),我曾大膽地做過(guò)猜測(cè):linux kernel發(fā)生了踩內(nèi)存現(xiàn)象,導(dǎo)致devices kset對(duì)象被破壞。隨后做了各方面的努力來(lái)證明我的想法,結(jié)果發(fā)現(xiàn)幾乎都是在第493次加載wifi模塊時(shí)出現(xiàn)的panic問(wèn)題,這讓我很迷惑,如果是踩內(nèi)存怎么可能固定在493次發(fā)生,雖然不能完全證明這個(gè)猜想是錯(cuò)誤的,但這足以說(shuō)明我的方向有問(wèn)題。
如此反反復(fù)復(fù),花費(fèi)了我兩個(gè)星期的時(shí)間才搞定這個(gè)panic,因此,kernel panic雖然難啃,但只要你愿意去嘗試愿意去努力,就算最后拿不下這個(gè)panic,你也會(huì)學(xué)到很多很多的東西,包括linux kernel行為,這些會(huì)對(duì)你以后的學(xué)習(xí)產(chǎn)生很大的影響,在碰到這類問(wèn)題一定是信心滿滿的。
7. 小結(jié)
linux oops()()的介紹就聊到這里吧,感謝你花時(shí)間閱讀本站內(nèi)容,更多關(guān)于linux oops(),不知所措的Linux:oops函數(shù),linux 一個(gè)核 kernal panic后,其他核怎么辦的信息別忘了在本站進(jìn)行查找喔。
創(chuàng)新互聯(lián)網(wǎng)絡(luò)推廣網(wǎng)站建設(shè),網(wǎng)站設(shè)計(jì),網(wǎng)站建設(shè)公司,網(wǎng)站制作,網(wǎng)頁(yè)設(shè)計(jì),1500元定制網(wǎng)站優(yōu)化全包,先排名后付費(fèi),已為上千家服務(wù),聯(lián)系電話:13518219792
網(wǎng)頁(yè)題目:不知所措的Linux:oops函數(shù)(linuxoops())
本文鏈接:http://www.dlmjj.cn/article/dpjshpj.html


咨詢
建站咨詢
