




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、zz 程序錯(cuò)誤檢測(cè)工具zz程序錯(cuò)誤檢測(cè)工具2010-06-21 16:53來(lái)源:Steve Best()JFS核心小組成員,IBM 2002年8月您可以用各種方法來(lái)監(jiān)控運(yùn)行著的用戶空間程序:可以為其運(yùn)行調(diào)試器并單步調(diào)試該程序,添加打印語(yǔ)句,或者添加工具來(lái)分析程序。本文描述了幾種可以用來(lái)調(diào)試在Linux上運(yùn)行的程序的方法。我們將回顧四種調(diào)試問(wèn)題的情況,這些問(wèn)題包括段錯(cuò)誤,內(nèi)存溢出和泄漏,還有掛起。本文討論了四種調(diào)試Linux程序的情況。在第1種情況中,我們使用了兩個(gè)有內(nèi)存分配問(wèn)題的樣本程序,使用MEMWATCH和Yet Another Malloc Debugger(YAMD)工具來(lái)調(diào)試它們。在
2、第2種情況中,我們使用了Linux中的strace實(shí)用程序,它能夠跟蹤系統(tǒng)調(diào)用和信號(hào),從而找出程序發(fā)生錯(cuò)誤的地方。在第3種情況中,我們使用Linux內(nèi)核的Oops功能來(lái)解決程序的段錯(cuò)誤,并向您展示如何設(shè)置內(nèi)核源代碼級(jí)調(diào)試器(kernel source level debugger,kgdb),以使用GNU調(diào)試器(GNU debugger,gdb)來(lái)解決相同的問(wèn)題;kgdb程序是使用串行連接的Linux內(nèi)核遠(yuǎn)程gdb。在第4種情況中,我們使用Linux上提供的魔術(shù)鍵控順序(magic key sequence)來(lái)顯示引發(fā)掛起問(wèn)題的組件的信息。常見(jiàn)調(diào)試方法當(dāng)您的程序中包含錯(cuò)誤時(shí),很可能在代碼中某處
3、有一個(gè)條件,您認(rèn)為它為真(true),但實(shí)際上是假(false)。找出錯(cuò)誤的過(guò)程也就是在找出錯(cuò)誤后推翻以前一直確信為真的某個(gè)條件過(guò)程。以下幾個(gè)示例是您可能確信成立的條件的一些類型:在源代碼中的某處,某變量有特定的值。在給定的地方,某個(gè)結(jié)構(gòu)已被正確設(shè)置。對(duì)于給定的if-then-else語(yǔ)句,if部分就是被執(zhí)行的路徑。當(dāng)子例程被調(diào)用時(shí),該例程正確地接收到了它的參數(shù)。找出錯(cuò)誤也就是要確定上述所有情況是否存在。如果您確信在子例程被調(diào)用時(shí)某變量應(yīng)該有特定的值,那么就檢查一下情況是否如此。如果您相信if結(jié)構(gòu)會(huì)被執(zhí)行,那么也檢查一下情況是否如此。通常,您的假設(shè)都會(huì)是正確的,但最終您會(huì)找到與假設(shè)不符的情況。
4、結(jié)果,您就會(huì)找出發(fā)生錯(cuò)誤的地方。調(diào)試是您無(wú)法逃避的任務(wù)。進(jìn)行調(diào)試有很多種方法,比如將消息打印到屏幕上、使用調(diào)試器,或只是考慮程序執(zhí)行的情況并仔細(xì)地揣摩問(wèn)題所在。在修正問(wèn)題之前,您必須找出它的源頭。舉例來(lái)說(shuō),對(duì)于段錯(cuò)誤,您需要了解段錯(cuò)誤發(fā)生在代碼的哪一行。一旦您發(fā)現(xiàn)了代碼中出錯(cuò)的行,請(qǐng)確定該方法中變量的值、方法被調(diào)用的方式以及關(guān)于錯(cuò)誤如何發(fā)生的詳細(xì)情況。使用調(diào)試器將使找出所有這些信息變得很簡(jiǎn)單。如果沒(méi)有調(diào)試器可用,您還可以使用其它的工具。(請(qǐng)注意,產(chǎn)品環(huán)境中可能并不提供調(diào)試器,而且Linux內(nèi)核沒(méi)有內(nèi)建的調(diào)試器。)實(shí)用的內(nèi)存和內(nèi)核工具您可以使用Linux上的調(diào)試工具,通過(guò)各種方式跟蹤用戶空間和內(nèi)
5、核問(wèn)題。請(qǐng)使用下面的工具和技術(shù)來(lái)構(gòu)建和調(diào)試您的源代碼:用戶空間工具:內(nèi)存工具:MEMWATCH和YAMD strace GNU調(diào)試器(gdb)魔術(shù)鍵控順序內(nèi)核工具:內(nèi)核源代碼級(jí)調(diào)試器(kgdb)內(nèi)建內(nèi)核調(diào)試器(kdb)Oops本文將討論一類通過(guò)人工檢查代碼不容易找到的問(wèn)題,而且此類問(wèn)題只在很少見(jiàn)的情況下存在。內(nèi)存錯(cuò)誤通常在多種情況同時(shí)存在時(shí)出現(xiàn),而且您有時(shí)只能在部署程序之后才能發(fā)現(xiàn)內(nèi)存錯(cuò)誤。第1種情況:內(nèi)存調(diào)試工具C語(yǔ)言作為L(zhǎng)inux系統(tǒng)上標(biāo)準(zhǔn)的編程語(yǔ)言給予了我們對(duì)動(dòng)態(tài)內(nèi)存分配很大的控制權(quán)。然而,這種自由可能會(huì)導(dǎo)致嚴(yán)重的內(nèi)存管理問(wèn)題,而這些問(wèn)題可能導(dǎo)致程序崩潰或隨時(shí)間的推移導(dǎo)致性能降級(jí)。內(nèi)存泄
6、漏(即malloc()內(nèi)存在對(duì)應(yīng)的free()調(diào)用執(zhí)行后永不被釋放)和緩沖區(qū)溢出(例如對(duì)以前分配到某數(shù)組的內(nèi)存進(jìn)行寫操作)是一些常見(jiàn)的問(wèn)題,它們可能很難檢測(cè)到。這一部分將討論幾個(gè)調(diào)試工具,它們極大地簡(jiǎn)化了檢測(cè)和找出內(nèi)存問(wèn)題的過(guò)程。MEMWATCH MEMWATCH由Johan Lindh編寫,是一個(gè)開(kāi)放源代碼C語(yǔ)言內(nèi)存錯(cuò)誤檢測(cè)工具,您可以自己下載它(請(qǐng)參閱本文后面部分的參考資料)。只要在代碼中添加一個(gè)頭文件并在gcc語(yǔ)句中定義了MEMWATCH之后,您就可以跟蹤程序中的內(nèi)存泄漏和錯(cuò)誤了。MEMWATCH支持ANSI C,它提供結(jié)果日志紀(jì)錄,能檢測(cè)雙重釋放(double-free)、錯(cuò)誤釋放(e
7、rroneous free)、沒(méi)有釋放的內(nèi)存(unfreed memory)、溢出和下溢等等。清單1.內(nèi)存樣本(test1.c)#includeSTDLIB.H#includeSTDIO.H#includememwatch.hint main(void)char*ptr1;char*ptr2;ptr1=malloc(512);ptr2=malloc(512);ptr2=ptr1;free(ptr2);free(ptr1);清單1中的代碼將分配兩個(gè)512字節(jié)的內(nèi)存塊,然后指向第一個(gè)內(nèi)存塊的指針被設(shè)定為指向第二個(gè)內(nèi)存塊。結(jié)果,第二個(gè)內(nèi)存塊的地址丟失,從而產(chǎn)生了內(nèi)存泄漏。現(xiàn)在我們編譯清單1的memw
8、atch.c。下面是一個(gè)makefile示例:test1 gcc-DMEMWATCH-DMW_STDIO test1.c memwatch c-o test1當(dāng)您運(yùn)行test1程序后,它會(huì)生成一個(gè)關(guān)于泄漏的內(nèi)存的報(bào)告。清單2展示了示例memwatch.log輸出文件。清單2.test1 memwatch.log文件MEMWATCH 2.67 Copyright(C)1992-1999 Johan Lindh.double-free:4 test1.c(15),0x80517b4 was freed from test1.c(14).unfreed:2 test1.c(11),512 bytes
9、 at 0x80519e4FE FE FE FE FE FE FE FE FE FE FE FE.Memory usage statistics(global):N)umber of allocations made:2 L)argest memory usage:1024 T)otal of all alloc()calls:1024 U)nfreed bytes totals:512 MEMWATCH為您顯示真正導(dǎo)致問(wèn)題的行。如果您釋放一個(gè)已經(jīng)釋放過(guò)的指針,它會(huì)告訴您。對(duì)于沒(méi)有釋放的內(nèi)存也一樣。日志結(jié)尾部分顯示統(tǒng)計(jì)信息,包括泄漏了多少內(nèi)存,使用了多少內(nèi)存,以及總共分配了多少內(nèi)存。YAMD
10、YAMD軟件包由Nate Eldredge編寫,可以查找C和C+中動(dòng)態(tài)的、與內(nèi)存分配有關(guān)的問(wèn)題。在撰寫本文時(shí),YAMD的最新版本為0.32。請(qǐng)下載yamd-0.32.tar.gz(請(qǐng)參閱參考資料)。執(zhí)行make命令來(lái)構(gòu)建程序;然后執(zhí)行make install命令安裝程序并設(shè)置工具。一旦您下載了YAMD之后,請(qǐng)?jiān)趖est1.c上使用它。請(qǐng)刪除#include memwatch.h并對(duì)makefile進(jìn)行如下小小的修改:使用YAMD的test1 gcc-g test1.c-o test1清單3展示了來(lái)自test1上的YAMD的輸出。清單3.使用YAMD的test1輸出YAMD version 0.
11、32 Executable:/usr/src/test/yamd-0.32/test1.INFO:Normal allocation of this block Address 0x40025e00,size 512.INFO:Normal allocation of this block Address 0x40028e00,size 512.INFO:Normal deallocation of this block Address 0x40025e00,size 512.ERROR:Multiple freeing At free of pointer already freed Add
12、ress 0x40025e00,size 512.WARNING:Memory leak Address 0x40028e00,size 512 WARNING:Total memory leaks:1 unfreed allocations totaling 512 bytes*Finished at Tue.10:07:15 2002 Allocated agrand total of 1024 bytes 2allocations Average of 512 bytes per allocation Max bytes allocated at one time:1024 24 Kal
13、loced internally/12 Kmapped now/8 Kmax Virtual program size is 1416 KEnd.YAMD顯示我們已經(jīng)釋放了內(nèi)存,而且存在內(nèi)存泄漏。讓我們?cè)谇鍐?中另一個(gè)樣本程序上試試YAMD。清單4.內(nèi)存代碼(test2.c)#includeSTDLIB.H#includeSTDIO.Hint main(void)char*ptr1;char*ptr2;char*chptr;int i=1;ptr1=malloc(512);ptr2=malloc(512);chptr=(char*)malloc(512);for(i;i=512;i+)chpt
14、r=S;ptr2=ptr1;free(ptr2);free(ptr1);free(chptr);您可以使用下面的命令來(lái)啟動(dòng)YAMD:./run-yamd/usr/src/test/test2/test2清單5顯示了在樣本程序test2上使用YAMD得到的輸出。YAMD告訴我們?cè)趂or循環(huán)中有越界(out-of-bounds)的情況。清單5.使用YAMD的test2輸出Running/usr/src/test/test2/test2 Temp output to/tmp/yamd-out.1243*./run-yamd:line 101:1248 Segmentation fault(core
15、dumped)YAMD version 0.32 Starting run:/usr/src/test/test2/test2 Executable:/usr/src/test/test2/test2 Virtual program size is 1380 K.INFO:Normal allocation of this block Address 0x40025e00,size 512.INFO:Normal allocation of this block Address 0x40028e00,size 512.INFO:Normal allocation of this block A
16、ddress 0x4002be00,size 512 ERROR:Crash.Tried to write address 0x4002c000 Seems to be part of this block:Address 0x4002be00,size 512.Address in question is at offset 512(out of bounds)Will dump core after checking heap.Done.MEMWATCH和YAMD都是很有用的調(diào)試工具,它們的使用方法有所不同。對(duì)于MEMWATCH,您需要添加包含文件memwatch.h并打開(kāi)兩個(gè)編譯時(shí)間標(biāo)記
17、。對(duì)于鏈接(link)語(yǔ)句,YAMD只需要-g選項(xiàng)。Electric Fence多數(shù)Linux分發(fā)版包含一個(gè)Electric Fence包,不過(guò)您也可以選擇下載它。Electric Fence是一個(gè)由Bruce Perens編寫的malloc()調(diào)試庫(kù)。它就在您分配內(nèi)存后分配受保護(hù)的內(nèi)存。如果存在fencepost錯(cuò)誤(超過(guò)數(shù)組末尾運(yùn)行),程序就會(huì)產(chǎn)生保護(hù)錯(cuò)誤,并立即結(jié)束。通過(guò)結(jié)合Electric Fence和gdb,您可以精確地跟蹤到哪一行試圖訪問(wèn)受保護(hù)內(nèi)存。Electric Fence的另一個(gè)功能就是能夠檢測(cè)內(nèi)存泄漏。第2種情況:使用strace strace命令是一種強(qiáng)大的工具,它能夠顯
18、示所有由用戶空間程序發(fā)出的系統(tǒng)調(diào)用。strace顯示這些調(diào)用的參數(shù)并返回符號(hào)形式的值。strace從內(nèi)核接收信息,而且不需要以任何特殊的方式來(lái)構(gòu)建內(nèi)核。將跟蹤信息發(fā)送到應(yīng)用程序及內(nèi)核開(kāi)發(fā)者都很有用。在清單6中,分區(qū)的一種格式有錯(cuò)誤,清單顯示了strace的開(kāi)頭部分,內(nèi)容是關(guān)于調(diào)出創(chuàng)建文件系統(tǒng)操作(mkfs)的。strace確定哪個(gè)調(diào)用導(dǎo)致問(wèn)題出現(xiàn)。清單6.mkfs上strace的開(kāi)頭部分execve(/sbin/mkfs.jfs,mkfs.jfs,-f,/dev/test1,&.open(/dev/test1,O_RDWR|O_LARGE stat64(/dev/test1,st_mode=&
19、,st_rdev=makedev(63,255),.)=0 ioctl(4,0x 40041271,0xbfffe128)=-1 EINVAL(Invalid argument)write(2,mkfs.jfs:warning-cannot setb.,98mkfs.jfs:warning-cannot set blocksize on block device/dev/test1:Invalid argument)=98 stat64(/dev/test1,st_mode=&,st_rdev=makedev(63,255),.)=0 open(/dev/test1,O_RDONLY|O_LA
20、RGE ioctl(5,0x 80041272,0xbfffe124)=-1 EINVAL(Invalid argument)write(2,mkfs.jfs:cant determine device.,._exit(1)=?清單6顯示ioctl調(diào)用導(dǎo)致用來(lái)格式化分區(qū)的mkfs程序失敗。ioctl BLKGETSIZE64失敗。(BLKGET-SIZE64在調(diào)用ioctl的源代碼中定義。)BLKGETSIZE64 ioctl將被添加到Linux中所有的設(shè)備,而在這里,邏輯卷管理器還不支持它。因此,如果BLKGETSIZE64 ioctl調(diào)用失敗,mkfs代碼將改為調(diào)用較早的ioctl調(diào)用;這
21、使得mkfs適用于邏輯卷管理器。第3種情況:使用gdb和Oops您可以從命令行使用gdb程序(Free Software Foundation的調(diào)試器)來(lái)找出錯(cuò)誤,也可以從諸如Data Display Debugger(DDD)這樣的幾個(gè)圖形工具之一使用gdb程序來(lái)找出錯(cuò)誤。您可以使用gdb來(lái)調(diào)試用戶空間程序或Linux內(nèi)核。這一部分只討論從命令行運(yùn)行g(shù)db的情況。使用gdb program name命令啟動(dòng)gdb。gdb將載入可執(zhí)行程序符號(hào)并顯示輸入提示符,讓您可以開(kāi)始使用調(diào)試器。您可以通過(guò)三種方式用gdb查看進(jìn)程:使用attach命令開(kāi)始查看一個(gè)已經(jīng)運(yùn)行的進(jìn)程;attach將停止進(jìn)程。使用
22、run命令執(zhí)行程序并從頭開(kāi)始調(diào)試程序。查看已有的核心文件來(lái)確定進(jìn)程終止時(shí)的狀態(tài)。要查看核心文件,請(qǐng)用下面的命令啟動(dòng)gdb。gdb programname core要用核心文件進(jìn)行調(diào)試,您不僅需要程序的可執(zhí)行文件和源文件,還需要核心文件本身。要用核心文件啟動(dòng)gdb,請(qǐng)使用-c選項(xiàng):gdb-c core programname gdb顯示哪行代碼導(dǎo)致程序發(fā)生核心轉(zhuǎn)儲(chǔ)。在運(yùn)行程序或連接到已經(jīng)運(yùn)行的程序之前,請(qǐng)列出您覺(jué)得有錯(cuò)誤的源代碼,設(shè)置斷點(diǎn),然后開(kāi)始調(diào)試程序。您可以使用help命令查看全面的gdb在線幫助和詳細(xì)的教程。kgdb kgdb程序(使用gdb的遠(yuǎn)程主機(jī)Linux內(nèi)核調(diào)試器)提供了一種使用
23、gdb調(diào)試Linux內(nèi)核的機(jī)制。kgdb程序是內(nèi)核的擴(kuò)展,它讓您能夠在遠(yuǎn)程主機(jī)上運(yùn)行g(shù)db時(shí)連接到運(yùn)行用kgdb擴(kuò)展的內(nèi)核機(jī)器。您可以接著深入到內(nèi)核中、設(shè)置斷點(diǎn)、檢查數(shù)據(jù)并進(jìn)行其它操作(類似于您在應(yīng)用程序上使用gdb的方式)。這個(gè)補(bǔ)丁的主要特點(diǎn)之一就是運(yùn)行g(shù)db的主機(jī)在引導(dǎo)過(guò)程中連接到目標(biāo)機(jī)器(運(yùn)行要被調(diào)試的內(nèi)核)。這讓您能夠盡早開(kāi)始調(diào)試。請(qǐng)注意,補(bǔ)丁為L(zhǎng)inux內(nèi)核添加了功能,所以gdb可以用來(lái)調(diào)試Linux內(nèi)核。使用kgdb需要兩臺(tái)機(jī)器:一臺(tái)是開(kāi)發(fā)機(jī)器,另一臺(tái)是測(cè)試機(jī)器。一條串行線(空調(diào)制解調(diào)器電纜)將通過(guò)機(jī)器的串口連接它們。您希望調(diào)試的內(nèi)核在測(cè)試機(jī)器上運(yùn)行;gdb在開(kāi)發(fā)機(jī)器上運(yùn)行。gdb
24、使用串行線與您要調(diào)試的內(nèi)核通信。請(qǐng)遵循下面的步驟來(lái)設(shè)置kgdb調(diào)試環(huán)境:下載您的Linux內(nèi)核版本適用的補(bǔ)丁。將組件構(gòu)建到內(nèi)核,因?yàn)檫@是使用kgdb最簡(jiǎn)單的方法。(請(qǐng)注意,有兩種方法可以構(gòu)建多數(shù)內(nèi)核組件,比如作為模塊或直接構(gòu)建到內(nèi)核中。舉例來(lái)說(shuō),日志紀(jì)錄文件系統(tǒng)(Journaled ,JFS)可以作為模塊構(gòu)建,或直接構(gòu)建到內(nèi)核中。通過(guò)使用gdb補(bǔ)丁,我們就可以將JFS直接構(gòu)建到內(nèi)核中。)應(yīng)用內(nèi)核補(bǔ)丁并重新構(gòu)建內(nèi)核。創(chuàng)建一個(gè)名為.gdbinit的文件,并將其保存在內(nèi)核源文件子目錄中(換句話說(shuō)就是/usr/src/linux)。文件.gdbinit中有下面四行代碼:set remotebaud 1
25、15200 symbol- target remote/dev/ttyS0 set output-radix 16將append=gdb這一行添加到lilo,lilo是用來(lái)在引導(dǎo)內(nèi)核時(shí)選擇使用哪個(gè)內(nèi)核的引導(dǎo)載入程序。image=/boot/bzImage-2.4.17 label=gdb2417 read-only root=/dev/sda8 append=gdb gdbttyS=1 gdb-baud=115200 nmi_watchdog=0清單7是一個(gè)腳本示例,它將您在開(kāi)發(fā)機(jī)器上構(gòu)建的內(nèi)核和模塊引入測(cè)試機(jī)器。您需要修改下面幾項(xiàng):bestsfb:用戶標(biāo)識(shí)和機(jī)器名。/usr/src/linu
26、x-2.4.17:內(nèi)核源代碼樹的目錄。bzImage-2.4.17:測(cè)試機(jī)器上將引導(dǎo)的內(nèi)核名。rcp和rsync:必須允許它在構(gòu)建內(nèi)核的機(jī)器上運(yùn)行。清單7.引入測(cè)試機(jī)器的內(nèi)核和模塊的腳本set-x rcp bestsfb:/usr/src/linux-2.4.17/arch/i386/boot/bzImage/boot/bzImage-2.4.17 rcp bestsfb:/usr/src/linux-2.4.17/System.map/boot/System.map-2.4.17 rm-rf/lib/modules/2.4.17 rsync-a bestsfb:/lib/modules/2.
27、4.17/lib/modules chown-R root/lib/modules/2.4.17 lilo現(xiàn)在我們可以通過(guò)改為使用內(nèi)核源代碼樹開(kāi)始的目錄來(lái)啟動(dòng)開(kāi)發(fā)機(jī)器上的gdb程序了。在本示例中,內(nèi)核源代碼樹位于/usr/src/linux-2.4.17。輸入gdb啟動(dòng)程序。如果一切正常,測(cè)試機(jī)器將在啟動(dòng)過(guò)程中停止。輸入gdb命令cont以繼續(xù)啟動(dòng)過(guò)程。一個(gè)常見(jiàn)的問(wèn)題是,空調(diào)制解調(diào)器電纜可能會(huì)被連接到錯(cuò)誤的串口。如果gdb不啟動(dòng),將端口改為第二個(gè)串口,這會(huì)使gdb啟動(dòng)。使用kgdb調(diào)試內(nèi)核問(wèn)題清單8列出了jfs_mount.c文件的源代碼中被修改過(guò)的代碼,我們?cè)诖a中創(chuàng)建了一個(gè)空指針異常,從而
28、使代碼在第109行產(chǎn)生段錯(cuò)誤。清單8.修改過(guò)后的jfs_mount.c代碼int jfs_mount(struct super_block*sb).int ptr;/*line 1added*/jFYI(1,(nMount JFSn);/*read/validate superblock*(initialize mount inode from the superblock)*/if(rc=chkSuper(sb)goto errout20;108 ptr=0;/*line 2added*/109 printk(%dn,*ptr);/*line 3added*/清單9在向文件系統(tǒng)發(fā)出mount
29、命令之后顯示一個(gè)gdb異常。kgdb提供了幾條命令,如顯示數(shù)據(jù)結(jié)構(gòu)和變量值以及顯示系統(tǒng)中的所有任務(wù)處于什么狀態(tài)、它們駐留在何處、它們?cè)谀男┑胤绞褂昧薈PU等等。清單9將顯示回溯跟蹤為該問(wèn)題提供的信息;where命令用來(lái)執(zhí)行反跟蹤,它將告訴被執(zhí)行的調(diào)用在代碼中的什么地方停止。清單9.gdb異常和反跟蹤mount-t jfs/dev/sdb/jfs Program received signal SIGSEGV,Segmentation fault.jfs_mount(sb=0xf78a3800)at jfs_mount.c:109 109 printk(%dn,*ptr);(gdb)where#
30、0 jfs_mount(sb=0xf78a3800)at jfs_mount.c:109#1 0xc01a0dbb in jfs_read_super.at super.c:280#2 0xc0149ff5 in get_sb_bdev.at super.c:620#3 0xc014a89f in do_kern_mount.at super.c:849#4 0xc0160e66 in do_add_mount.at namespace.c:569#5 0xc01610f4 in do_mount.at namespace.c:683#6 0xc01611ea in sys_mount.at
31、namespace.c:716#7 0xc01074a7 in system_call()at af_packet.c:1891#8 0x0 in?()(gdb)下一部分還將討論這個(gè)相同的JFS段錯(cuò)誤問(wèn)題,但不設(shè)置調(diào)試器,如果您在非kgdb內(nèi)核環(huán)境中執(zhí)行清單8中的代碼,那么它使用內(nèi)核可能生成的Oops消息。Oops分析Oops(也稱panic,慌張)消息包含系統(tǒng)錯(cuò)誤的細(xì)節(jié),如CPU寄存器的內(nèi)容。在Linux中,調(diào)試系統(tǒng)崩潰的傳統(tǒng)方法是分析在發(fā)生崩潰時(shí)發(fā)送到系統(tǒng)控制臺(tái)的Oops消息。一旦您掌握了細(xì)節(jié),就可以將消息發(fā)送到ksymoops實(shí)用程序,它將試圖將代碼轉(zhuǎn)換為指令并將堆棧值映射到內(nèi)核符號(hào)。在
32、很多情況下,這些信息就足夠您確定錯(cuò)誤的可能原因是什么了。請(qǐng)注意,Oops消息并不包括核心文件。讓我們假設(shè)系統(tǒng)剛剛創(chuàng)建了一條Oops消息。作為編寫代碼的人,您希望解決問(wèn)題并確定什么導(dǎo)致了Oops消息的產(chǎn)生,或者您希望向顯示了Oops消息的代碼的開(kāi)發(fā)者提供有關(guān)您的問(wèn)題的大部分信息,從而及時(shí)地解決問(wèn)題。Oops消息是等式的一部分,但如果不通過(guò)ksymoops程序運(yùn)行它也于事無(wú)補(bǔ)。下面的圖顯示了格式化Oops消息的過(guò)程。格式化Oops消息ksymoops需要幾項(xiàng)內(nèi)容:Oops消息輸出、來(lái)自正在運(yùn)行的內(nèi)核的System.map文件,還有/proc/ksyms、vmlinux和/proc/modules。
33、關(guān)于如何使用ksymoops,內(nèi)核源代碼/usr/src/linux/Documentation/oops-tracing.txt中或ksymoops手冊(cè)頁(yè)上有完整的說(shuō)明可以參考。Ksymoops反匯編代碼部分,指出發(fā)生錯(cuò)誤的指令,并顯示一個(gè)跟蹤部分表明代碼如何被調(diào)用。首先,將Oops消息保存在一個(gè)文件中以便通過(guò)ksymoops實(shí)用程序運(yùn)行它。清單10顯示了由安裝JFS文件系統(tǒng)的mount命令創(chuàng)建的Oops消息,問(wèn)題是由清單8中添加到JFS安裝代碼的那三行代碼產(chǎn)生的。清單10.ksymoops處理后的Oops消息ksymoops 2.4.0 on i686 2.4.17.Options use
34、d.15:59:37 sfb1 kernel:Unable to handle kernel NULL pointer dereference at virtual address 0000000.15:59:37 sfb1 kernel:c01588fc.15:59:37 sfb1 kernel:*pde=0000000.15:59:37 sfb1 kernel:Oops:0000.15:59:37 sfb1 kernel:CPU:0.15:59:37 sfb1 kernel:EIP:0010:jfs_mount+60/704.15:59:37 sfb1 kernel:Call Trace:
35、jfs_read_super+287/688get_sb_bdev+563/736do_kern_mount+189/336do_add_mount+35/208do_page_fault+0/1264.15:59:37 sfb1 kernel:Call Trace:.15:59:37 sfb1 kernel:EIP;c01588fc=.Trace;c0106cf3 Code;c01588fc 00000000 _EIP:Code;c01588fc=0:8b 2d 00 00 00 00 mov 0x0,%ebp=Code;c 0158902 6:55 push%ebp接下來(lái),您要確定jfs_
36、mount中的哪一行代碼引起了這個(gè)問(wèn)題。Oops消息告訴我們問(wèn)題是由位于偏移地址3c的指令引起的。做這件事的辦法之一是對(duì)jfs_mount.o文件使用objdump實(shí)用程序,然后查看偏移地址3c。Objdump用來(lái)反匯編模塊函數(shù),看看您的C源代碼會(huì)產(chǎn)生什么匯編指令。清單11顯示了使用objdump后您將看到的內(nèi)容,接著,我們查看jfs_mount的C代碼,可以看到空值是第109行引起的。偏移地址3c之所以很重要,是因?yàn)镺ops消息將該處標(biāo)識(shí)為引起問(wèn)題的位置。清單11.jfs_mount的匯編程序清單109 printk(%dn,*ptr);objdump jfs_mount.o jfs_mou
37、nt.o: elf32-i386 Disassembly of section.text:0:55 push%ebp.2c:e8 cf 03 00 00 call 400 31:89 c3 mov%eax,%ebx 33:58 pop%eax 34:85 db test%ebx,%ebx 36:0f 85 55 02 00 00 jne 291 3c:8b 2d 00 00 00 00 mov 0x0,%ebp problem line above 42:55 push%ebp kdb Linux內(nèi)核調(diào)試器(Linux kernel debugger,kdb)是Linux內(nèi)核的補(bǔ)丁,它提供了一種在系統(tǒng)能運(yùn)行時(shí)對(duì)內(nèi)核內(nèi)存和數(shù)據(jù)結(jié)構(gòu)進(jìn)行檢查的辦法。請(qǐng)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 餐飲業(yè)食品安全管理體系認(rèn)證合同
- 小米c面試題及答案
- 市容環(huán)衛(wèi)外包方案
- 輕工產(chǎn)品倉(cāng)儲(chǔ)倉(cāng)單質(zhì)押擔(dān)保協(xié)議
- 汽車售后服務(wù)網(wǎng)點(diǎn)車輛訂購(gòu)及維修服務(wù)合同
- 社區(qū)改造設(shè)計(jì)建筑方案
- 生態(tài)造林工程投標(biāo)方案
- 黨章知識(shí)課件
- 數(shù)學(xué)小升初面試題及答案
- 體育協(xié)會(huì)換屆方案
- 廠房圍墻承包協(xié)議書
- 國(guó)際壓力性損傷-潰瘍預(yù)防和治療臨床指南(2025年版)解讀
- 熊貓旅居簽署協(xié)議書
- 心衰藥物治療進(jìn)展課件
- 化工儀表管理與維護(hù)
- 2024年“藍(lán)橋杯”科學(xué)素養(yǎng)競(jìng)賽考試題庫(kù)(含答案)
- 風(fēng)力發(fā)電運(yùn)維值班員(技師)職業(yè)技能鑒定考試題(附答案)
- 2025年上半年潛江市城市建設(shè)發(fā)展集團(tuán)招聘工作人員【52人】易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 廣東省惠州市惠城區(qū)2024-2025 學(xué)年度第一學(xué)期期末教學(xué)質(zhì)量檢測(cè)八年級(jí)道德與法治試卷及答案(含答案)
- 血站生物安全培訓(xùn)課件
- 現(xiàn)場(chǎng)外傷急救技術(shù)
評(píng)論
0/150
提交評(píng)論