?? (ldd) ch04-調(diào)試技術(shù)(轉(zhuǎn)載).htm
字號:
color=#ffffff size=3>
<P><BR>(代碼)<BR> <BR>由于read從它的小緩沖區(qū)(faulty_buf)復(fù)制數(shù)據(jù)到用戶空間,我們希望讀一小塊文件<BR>能夠工作。然而,每次讀出多于1KB的數(shù)據(jù)會跨越頁面邊界,如果訪問了非法頁面read就<BR>會失敗。事實上,前面給出的oops是在請求一個4KB大小的read時發(fā)生的,這條消息在/v<BR>ar/log/messages(syslogd默認存放內(nèi)核消息的文件)的oops消息前給出了:<BR> <BR>(代碼)<BR> <BR>同樣的cat命令卻不能在Alpha上產(chǎn)生oops,這是因為從faulty_buf讀取4KB字節(jié)沒有超出<BR>頁邊界(Alpha上的頁面大小是8KB,緩沖區(qū)正好在頁面的起始位置附近)。如果在你的<BR>系統(tǒng)上讀取faulty沒有產(chǎn)生oops,試試wc,或者給dd顯式地指定塊大小。<BR> <BR>使用ksymoops<BR>oops消息的最大問題就是十六進制數(shù)值對于程序員來說沒什么意義;需要將它們解析為<BR>符號。<BR> <BR>內(nèi)核源碼通過其所包含的ksymoops工具幫助開發(fā)人員――但是注意,版本1.2的源碼中沒<BR>有這個程序。該工具將oops消息中的數(shù)值地址解析為內(nèi)核符號,但只限于PC機產(chǎn)生的oop<BR>s消息。由于消息本身就是處理器相關(guān)的,每一體系結(jié)構(gòu)都有其自身的消息格式。<BR> <BR>ksymoops從標(biāo)準(zhǔn)輸入獲得oops消息,并從命令行內(nèi)核符號表的名字。符號表通常就是/us<BR></P></FONT><FONT
color=#ffffff size=3>
<P>ksymoops從標(biāo)準(zhǔn)輸入獲得oops消息,并從命令行內(nèi)核符號表的名字。符號表通常就是/us<BR>r/src/linux/System.map。程序以更可讀的方式打印調(diào)用軌跡和程序代碼,而不是最原<BR>始的oops消息。下面的片斷就是用上一節(jié)的oops消息得出的結(jié)果:<BR> <BR>(代碼)<BR> <BR>由ksymoops反匯編出的代碼給出了失效的指令和其后的指令。很明顯――對于那些知道<BR>一點匯編的人――repz movsl指令(REPeat till cx is Zero, MOVe a String of<BR>Longs)用源索引(esi,是0x202e000)訪問了一個未映射頁面。用來獲得模塊信息的ks<BR>ymoops -m命令給出,模塊映射到一個在0x0202dxxx的頁面上,這也確認樂esi確實超出<BR>了范圍。<BR> <BR>由于faulty模塊所占用的內(nèi)存不在系統(tǒng)表中,被解碼的調(diào)用軌跡還給出了兩個數(shù)值地址<BR>。這些值可以手動補充,或是通過ksyms命令的輸出,或是在/proc/ksyms中查詢模塊的<BR>名字。<BR> <BR>然而對于這個失效,這兩個地址并不對應(yīng)與代碼地址。如果你看了arch/i386/kernel/tr<BR>aps.c,你就發(fā)現(xiàn),調(diào)用軌跡是從整個堆棧并利用一些啟發(fā)式方法區(qū)分數(shù)據(jù)值(本地變量<BR>和函數(shù)參數(shù))和返回地址獲得的。調(diào)用軌跡中只給出了引用內(nèi)核代碼的地址和引用模塊<BR>的地址。由于模塊所占頁面既有代碼也有數(shù)據(jù),錯綜復(fù)雜的棧可能會漏掉啟發(fā)式信息,<BR>這就是上面兩個0x202xxxx地址的情況。<BR> <BR>如果你不愿手動查看模塊地址,下面這組管道可以用來創(chuàng)建一個既有內(nèi)核又有模塊符號<BR></P></FONT><FONT
color=#ffffff size=3>
<P>如果你不愿手動查看模塊地址,下面這組管道可以用來創(chuàng)建一個既有內(nèi)核又有模塊符號<BR>的符號表。無論何時你加載模塊,你都必須重新創(chuàng)建這個符號表。<BR> <BR>(代碼)<BR> <BR>這個管道將完整的系統(tǒng)表與/proc/ksyms中的公開內(nèi)核符號混合在一起,后者除了內(nèi)核符<BR>號外,還包括了當(dāng)前內(nèi)核里的模塊符號。這些地址在insmod重定位代碼后就出現(xiàn)在/proc<BR>/ksyms中。由于這兩個文件的格式不同,使用了sed和awk將所有的文本行轉(zhuǎn)換為一種合<BR>適的格式。然后對這張表排序,去除重復(fù)部分,這樣ksymoops就可以用了。<BR> <BR>如果我們重新運行ksymoops,它從新的符號表中截取出如下信息:<BR> <BR>(代碼)<BR> <BR>正如你所見到的,當(dāng)跟蹤與模塊有關(guān)的oops消息時,創(chuàng)建一個修訂的系統(tǒng)表是很有助益<BR>的:現(xiàn)在ksymoops能夠?qū)χ噶钪羔樈獯a并完成整個調(diào)用軌跡了。還要注意,顯式反匯編<BR>碼的格式和objdump所使用的格式一樣。objdump也是一個功能強大的工具;如果你需要<BR>查看失敗前的指令,你調(diào)用命令objdump –d faulty.o。<BR> <BR>在文件的匯編列表中,字串faulty_read+45/60標(biāo)記為失效行。有關(guān)objdump的更多的信<BR>息和它的命令行選項可以參見該命令的手冊。<BR> <BR>即便你構(gòu)建了你自己的修訂版符號表,上面提到的有關(guān)調(diào)用軌跡的問題仍然存在:雖然0<BR></P></FONT><FONT
color=#ffffff size=3>
<P>即便你構(gòu)建了你自己的修訂版符號表,上面提到的有關(guān)調(diào)用軌跡的問題仍然存在:雖然0<BR>x202xxxx指針被解碼了,但仍然是假的。<BR> <BR>學(xué)會解碼oops消息需要一定的經(jīng)驗,但是確實值得一做。用來學(xué)習(xí)的時間很快就會有所<BR>回報。不過由于機器指令的Unix語法與Intel語法不同,唯一的問題在于從哪獲得有關(guān)匯<BR>編語言的文檔;盡管你了解PC匯編語言,但你的經(jīng)驗都是用Intel語法的編程獲得的。在<BR>參考書目中,我給一些有所補益的書籍。<BR> <BR>使用oops<BR>使用ksymoops有些繁瑣。你需要C++編譯器編譯它,你還要構(gòu)建你自己的符號表來充分發(fā)<BR>揮程序的能力,你還要將原始消息和ksymoops輸出合在一起組成可用的信息。<BR> <BR>如果你不想找這么多麻煩,你可以使用oops程序。oops在本書的O’Reilly FTP站點給出<BR>的源碼中。它源自最初的ksymoops工具,現(xiàn)在它的作者已經(jīng)不維護這個工具了。oops是<BR>用C語言寫成的,而且直接查看/proc/ksyms而無需用戶每次加載模塊后構(gòu)建新的符號表<BR>。<BR> <BR>該程序試圖解碼所有的處理器寄存器并 顏 軌跡解析為符號值。它的缺點是,它要比ksy<BR>moops羅嗦些,但通常你所有的信息越多,你發(fā)現(xiàn)錯誤也就越快。oops的另一個優(yōu)點是,<BR>它可以解析x86,Alpha和Sparc的oops消息。與內(nèi)核源碼相同,這個程序也按GPL發(fā)行。<BR> <BR>oops產(chǎn)生的輸出與ksymoops的類似,但是更完全。這里給出前一個oops輸出的開始部分<BR>—由于在這個oops消息中堆棧沒保存什么有用的東西,我不認為應(yīng)該顯示整個 顏 軌跡<BR></P></FONT><FONT
color=#ffffff size=3>
<P>—由于在這個oops消息中堆棧沒保存什么有用的東西,我不認為應(yīng)該顯示整個 顏 軌跡<BR>:<BR> <BR>(代碼)<BR> <BR>當(dāng)你調(diào)試“真正的”模塊(faulty太短了,沒有什么意義)時,將寄存器和堆棧解碼是<BR>非常有益的,而且如果被調(diào)試的所有模塊符號都開放出來時更有幫助。在失效時,處理<BR>器寄存器一般不會指向模塊的符號,只有當(dāng)符號表開放給/proc/ksyms時,你才能輸出中<BR>標(biāo)別它們。<BR> <BR>我們可以用一下步驟制作一張更完整的符號表。首先,我們不應(yīng)在模塊中聲明靜態(tài)變量<BR>,否則我們就無法用insmod開放它們了。第二,如下面的截取自scull的init_module函<BR>數(shù)的代碼所示,我們可以用#ifdef SCULL_DEBUG或類似的宏屏蔽register_symtab調(diào)用。<BR> <BR> <BR>(代碼)<BR> <BR>我們在第2章“編寫和運行模塊”的“注冊符號表”一節(jié)中已經(jīng)看到了類似內(nèi)容,那里說<BR>,如果模塊不注冊符號表,所有的全局符號就都開放。盡管這一功能僅在SCULL_DEBUG被<BR>激活時才有效,為了避免內(nèi)核中的名字空間污染,所有的全局符號有合適的前綴(參見<BR>第2章的“模塊與應(yīng)用程序”一節(jié))。<BR> <BR>使用klogd<BR></P></FONT><FONT
color=#ffffff size=3>
<P>使用klogd<BR>klogd守護進程的近期版本可以在oops存放到記錄文件前對oops消息解碼。解碼過程只由<BR>版本1.3或更新版本的守護進程完成,而且只有將-k /usr/src/linux/System.map做為參<BR>數(shù)傳遞給守護進程時才解碼。(你可以用其他符號表文件代替System.map)<BR> <BR>有新的klogd給出的faulty的oops如下所示,它寫到了系統(tǒng)記錄中:<BR> <BR>(代碼)<BR> <BR>我想能解碼的klogd對于調(diào)試一般的Linux安裝的核心來說是很好的工具。由klogd解碼的<BR>消息包括大部分ksymoops的功能,而且也要求用戶編譯額外的工具,或是,當(dāng)系統(tǒng)出現(xiàn)<BR>故障時,為了給出完整的錯誤報告而合并兩個輸出。當(dāng)oops發(fā)生在內(nèi)核時,守護進程還<BR>會正確地解碼指令指針。它并不反匯編代碼,但這不是問題,當(dāng)錯誤報告給出消息時,<BR>二進制數(shù)據(jù)仍然存在,可以離線反匯編代碼。<BR> <BR>守護進程的另一個功能就是,如果符號表版本與當(dāng)前內(nèi)核不匹配,它會拒絕解析符號。<BR>如果在系統(tǒng)記錄中解析出了符號,你可以確信它是正確的解碼。<BR> <BR>然而,盡管它對Linux用戶很有幫助,這個工具在調(diào)試模塊時沒有什么幫助。我個人沒有<BR>在開放軟件的電腦里使用解碼選項。klogd的問題是它不解析模塊中的符號;因為守護進<BR>程在程序員加載模塊前就已經(jīng)運行了,即使讀了/proc/ksyms也不會有什么幫助。記錄文<BR>件中存在解析后的符號會使oops和ksymoops混淆,造成進一步解析的困難。<BR> <BR></P></FONT><FONT
color=#ffffff size=3>
<P><BR>如果你需要使用klogd調(diào)試你的模塊,最新版本的守護進程需要加入一些新的特殊支持,<BR>我期待它的完成,只要給內(nèi)核打一個小補丁就可以了。<BR> <BR>系統(tǒng)掛起<BR>盡管內(nèi)核代碼中的大多數(shù)錯誤僅會導(dǎo)致一個oops消息,有時它們困難完全將系統(tǒng)掛起。<BR>如果系統(tǒng)掛起了,沒有消息能夠打印出來。例如,如果代碼遇到一個死循環(huán),內(nèi)核停止<BR>了調(diào)度過程,系統(tǒng)不會再響應(yīng)任何動作,包括魔法鍵Ctrl-Alt-Del組合。<BR> <BR>處理系統(tǒng)掛起有兩個選擇――一個是防范與未然,另一個就是亡羊補牢,在發(fā)生掛起后<BR>調(diào)試代碼。<BR> <BR>通過在策略點上插入schedule調(diào)用可以防止死循環(huán)。schedule調(diào)用(正如你所猜想到的<BR>)調(diào)用調(diào)度器,因此允許其他進程偷取當(dāng)然進程的CPU時間。如果進程因你的驅(qū)動程序中<BR>的錯誤而在內(nèi)核空間循環(huán),你可以在跟蹤到這種情況后殺掉這個進程。<BR> <BR>在驅(qū)動程序代碼中插入schedule調(diào)用會給程序員帶來新的“問題”:函數(shù),,以及調(diào)用軌<BR>跡中的所有函數(shù),必須是可重入的。在正常環(huán)境下,由于不同的進程可能并發(fā)地訪問設(shè)<BR>備,驅(qū)動程序做為整體是可重入的,但由于Linux內(nèi)核是不可搶占的,不必每個函數(shù)都是<BR>可重入的。但如果驅(qū)動程序函數(shù)允許調(diào)度器中斷當(dāng)前進程,另一個不同的進程可能會進<BR>入同一個函數(shù)。如果schedule調(diào)用僅在調(diào)試期間打開,如果你不允許,你可以避免兩個<BR>并發(fā)進程訪問驅(qū)動程序,所以并發(fā)性倒不是什么非常重要的問題。在介紹阻塞型操作時<BR>(第5章的“寫可重入代碼”)我們再詳細介紹并發(fā)性問題。<BR></P></FONT><FONT
color=#ffffff size=3>
<P>(第5章的“寫可重入代碼”)我們再詳細介紹并發(fā)性問題。<BR> <BR>如果要調(diào)試死循環(huán),你可以利用Linux鍵盤的特殊鍵。默認情況下,如果和修飾鍵一起按<BR>了PrScr鍵(鍵碼是70),系統(tǒng)會向當(dāng)前控制臺打印有關(guān)機器狀態(tài)的有用信息。這一功能<BR>在x86和Alpha系統(tǒng)都有。Linux的Sparc移植也有同樣的功能,但它使用了標(biāo)記為“Break<BR>/Scroll Lock”的鍵(鍵碼是30)。<BR> <BR>每一個特殊函數(shù)都有一個名字,并如下面所示都有一個按鍵事件與之對應(yīng)。組合鍵之后<BR>的括號里是函數(shù)名。<BR> <BR>Shift-PrScr(Show_Memory)<BR> <BR>打印若干行關(guān)于內(nèi)存使用的信息,尤其是有關(guān)緩沖區(qū)高速緩存的使用情況。<BR> <BR>Control-PrScr(Show_State)<BR> <BR>針對系統(tǒng)里的每一個處理器打印一行信息,同時還打印內(nèi)部進程樹。對當(dāng)前進程進行標(biāo)<BR>記。<BR> <BR>RightAlt-PrScr(Show_Registers)<BR> <BR>由于它可以打印按鍵時的處理器寄存器內(nèi)容,它是系統(tǒng)掛起時最重要的一個鍵了。如果<BR>有當(dāng)前內(nèi)核的系統(tǒng)表的話,查看指令計數(shù)器以及它如何隨時間變化,對了解代碼在何處<BR></P></FONT><FONT
color=#ffffff size=3>
<P>有當(dāng)前內(nèi)核的系統(tǒng)表的話,查看指令計數(shù)器以及它如何隨時間變化,對了解代碼在何處<BR>循環(huán)非常有幫助。<BR> <BR>如果想將這些函數(shù)映射到不同的鍵上,每一個函數(shù)名都可以做為參數(shù)傳遞給loadkeys。<BR>鍵盤映射表可以任意修改(這是“策略無關(guān)的”)。<BR> <BR>如果console_loglevel足夠到的話,這些函數(shù)打印的消息會出現(xiàn)在控制臺上。如果不是<BR>你運行了一個舊klogd和一個新內(nèi)核的話,默認記錄級應(yīng)該足夠了。如果沒有出現(xiàn)消息,<BR>你可以象以前說的那樣提升記錄級。“足夠高”的具體值與你使用的內(nèi)核版本有關(guān)。對<BR>于Linux 2.0或更新的版本來說是5。<BR> <BR>即便當(dāng)系統(tǒng)掛起時,消息也會打印到控制臺上,確認記錄級足夠高是非常重要的。消息<BR>是在產(chǎn)生中斷時生成的,因此即便有錯的進程不釋放CPU也可以運行――當(dāng)然,除非中斷<BR>被屏蔽了,不過如果發(fā)生這種情況既不太可能也非常不幸。<BR> <BR>有時系統(tǒng)看起來象是掛起了,但其實不是。例如,如果鍵盤因某種奇怪的原因被鎖住了<BR>就會發(fā)生這種情況。這種假掛起可以通過查看你為探明此種情況而運行的程序輸出來判<BR>斷。我有一個程序會不斷地更新LED顯示器上的時鐘,我發(fā)現(xiàn)這個對于驗證調(diào)度器尚在運<BR>行非常有用。你可以不必依賴外部設(shè)備就可以檢查調(diào)度器,你可以實現(xiàn)一個程序讓鍵盤L<BR>ED閃爍,或是不斷地打開關(guān)閉軟盤馬達,或是不斷觸動揚聲器――不過我個人認為,通<BR>常的蜂鳴聲很煩人,應(yīng)該盡量避免。看看ioctl命令KDMKTONE。O’Reilly FTP站點上的<BR>例子程序(misc-progs/heartbeat.c)中有一個是讓鍵盤LED不斷閃爍的。<BR> <BR></P></FONT><FONT
color=#ffffff size=3>
<P><BR>如果鍵盤不接收輸入了,最佳的處理手段是從網(wǎng)絡(luò)登錄在系統(tǒng)中,殺掉任何違例的進程<BR>,或是重新設(shè)置鍵盤(用kdb_mode -a)。然而,如果你沒有網(wǎng)絡(luò)可用來恢復(fù)的話,發(fā)現(xiàn)<BR>系統(tǒng)掛起是由鍵盤鎖死造成的一點兒用也沒有。如果情況確實是這樣,你應(yīng)該配置一種<BR>替代輸入設(shè)備,至少可以保證正常地重啟系統(tǒng)。對于你的計算機來說,關(guān)閉系統(tǒng)或重啟<BR>比起所謂的按“大紅鈕”要更方便一些,至少它可以免去長時間地fsck掃描磁盤。<BR> <BR>這種替代輸入設(shè)備可以是游戲桿或是鼠標(biāo)。在sunsite.edu.cn上有一個游戲桿重啟守護<BR>進程,gpm-1.10或更新的鼠標(biāo)服務(wù)器可以通過命令行選項支持類似的功能。如果鍵盤沒<BR>有鎖死,但是卻誤入“原始”模式,你可以看看kdb包中文檔介紹的一些小技巧。我建議<BR>最好在問題出現(xiàn)以前就看看這些文檔,否則就太晚了。另一種可能是配置gpm-root菜單<BR>,增添一個“reboot”或“reset keyboard”菜單項;gpm-root一個響應(yīng)控制鼠標(biāo)事件<BR>的守護進程,它用來在屏幕上顯示菜單和執(zhí)行所配置的動作。<BR> <BR>最好,你會可以按“留意安全鍵”(SAK),一個用于將系統(tǒng)恢復(fù)為可用狀態(tài)的特殊鍵。<BR>由于不是所有的實現(xiàn)都能用,當(dāng)前Linux版本的默認鍵盤表中沒有為此鍵特設(shè)一項。不過<BR>你還是可以用loadkeys將你的鍵盤上的一個鍵映射為SAK。你應(yīng)該看看drivers/char目錄<BR>中的SAK實現(xiàn)。代碼中的注釋解釋了為什么這個鍵在Linux 2.0中不是總能工作,這里我<BR>就不多說了。<BR> <BR>不過,如果你運行版本2.1.9或是更新的版本,你就可以使用非常可靠地留意安全鍵了。<BR>此外,2.1.43及后續(xù)版本內(nèi)核還有一個編譯選項選擇是否打開“SysRq魔法鍵”;我建議<BR>你看一看drivers/char/sysrq.c中的代碼并使用這項新技術(shù)。<BR></P></FONT><FONT
color=#ffffff size=3>
<P>你看一看drivers/char/sysrq.c中的代碼并使用這項新技術(shù)。<BR> <BR>如果你的驅(qū)動程序真的將系統(tǒng)掛起了,而且你有不知道在哪插入schedule調(diào)用,最佳的<BR>處理方法就是加一些打印消息,并將它們打印到控制臺上(通過修改console_loglevel<BR>變量值)。在重演掛起過程時,最好將所有的磁盤都以只讀方式安裝在系統(tǒng)上。如果磁<BR>盤是只讀的或沒有安裝,就不會存在破壞文件系統(tǒng)或使其進入不一致狀態(tài)的危險。至少<BR>你可以避免在復(fù)位系統(tǒng)后運行fsck。另一中方法就是使用NFS根計算機來測試模塊。在這<BR>種情況下,由于NFS服務(wù)器管理文件系統(tǒng)的一致性,而它又不會受你的驅(qū)動程序的影響,<BR>你可以避免任何的文件系統(tǒng)崩潰。<BR> <BR>使用調(diào)試器<BR>最后一種調(diào)試模塊的方法就是使用調(diào)試器來一步步地跟蹤代碼,查看變量和機器寄存器<BR>的值。這種方法非常耗時,應(yīng)該盡可能地避免。不過,某些情況下通過調(diào)試器對代碼進<BR>行細粒度的分析是非常有益的。在這里,我們所說的被調(diào)試的代碼運行在內(nèi)核空間――<BR>除非你遠程控制內(nèi)核,否則不可能一步步跟蹤內(nèi)核,這會使很多事情變得更加困難。由<BR>于遠程控制很少用到,我們最后介紹這項技術(shù)。所幸的是,在當(dāng)前版本的內(nèi)核中可以查<BR>看和修改變量。<BR> <BR>在這一級上熟練地使用調(diào)試器需要精通gdb命令,對匯編碼有一定了解,并且有能夠?qū)⒃?lt;BR>碼與優(yōu)化后的匯編碼對應(yīng)起來的能力。<BR> <BR>不幸的是,gdb更適合與調(diào)試核心而不是模塊,調(diào)試模塊化的代碼需要更多的技術(shù)。這更<BR>多的技術(shù)就是kdebug包,它利用gdb的“遠程調(diào)試”接口控制本地內(nèi)核。我將在介紹普通<BR></P></FONT><FONT
color=#ffffff size=3>
<P>多的技術(shù)就是kdebug包,它利用gdb的“遠程調(diào)試”接口控制本地內(nèi)核。我將在介紹普通<BR>調(diào)試器后介紹kdebug。<BR> <BR>使用gdb<BR>gdb在探究系統(tǒng)內(nèi)部行為時非常有用。啟動調(diào)試器時必須假想內(nèi)核就是一個應(yīng)用程序。除<BR>了指定內(nèi)核文件名外,你還應(yīng)該在命令行中提供內(nèi)存鏡象文件的名字。典型的gdb調(diào)用如<BR>下所示:<BR> <BR>(代碼)<BR> <BR>第一個參數(shù)是未經(jīng)壓縮的內(nèi)核可執(zhí)行文件(在你編譯完內(nèi)核后,這個文件在/usr/src/li<BR>nux目錄中)的名字。只有x86體系結(jié)構(gòu)有zImage文件(有時稱為vmlinuz),它是一種解<BR>決Intel處理器實模式下只有640KB限制的一種技巧;而無論在哪個平臺上,vmlinux都是<BR>你所編譯的未經(jīng)壓縮的內(nèi)核。<BR> <BR>gdb命令行的第二個參數(shù)是是內(nèi)存鏡象文件的名字。與其他在/proc下的文件類似,/proc<BR>/kcore也是在被讀取時產(chǎn)生的。當(dāng)read系統(tǒng)調(diào)用在/proc文件系統(tǒng)執(zhí)行時,它映射到一個<BR>用于數(shù)據(jù)生成而不是數(shù)據(jù)讀取的函數(shù)上;我們已在“使用/proc文件系統(tǒng)”一節(jié)中介紹了<BR>這個功能。系統(tǒng)用kcore來表示按內(nèi)存鏡象文件格式存儲的內(nèi)核“可執(zhí)行文件”;由于它<BR>要表示整個內(nèi)核地址空間,它是一個非常巨大的文件,對應(yīng)所有的物理內(nèi)存。利用gdb,<BR>你可以通過標(biāo)準(zhǔn)gdb命令查看內(nèi)核標(biāo)量。例如,p jiffies可以打印從系統(tǒng)啟動到當(dāng)前時<BR>刻的時鐘滴答數(shù)。<BR> <BR></P></FONT><FONT
color=#ffffff size=3>
<P><BR>當(dāng)你從gdb打印數(shù)據(jù)時,內(nèi)核還在運行,不同數(shù)據(jù)項會在不同時刻有不同的數(shù)值;然而,<BR>gdb為了優(yōu)化對內(nèi)存鏡象文件的訪問會將已經(jīng)讀到的數(shù)據(jù)緩存起來。如果你再次查看jiff<BR>ies變量,你會得到和以前相同的值。緩存變量值防止額外的磁盤操作對普通內(nèi)存鏡象文<BR>件來說是對的,但對“動態(tài)”內(nèi)存鏡象文件來說就不是很方便了。解決方法是在你想刷<BR>新gdb緩存的時候執(zhí)行core-file /proc/kcore命令;調(diào)試器將使用新的內(nèi)存鏡象文件并<BR>廢棄舊信息。但是,讀新數(shù)據(jù)時你并不總是需要執(zhí)行core-file命令;gdb以1KB的尺度讀<BR>取內(nèi)存鏡象文件,僅僅緩存它所引用的若干塊。<BR> <BR>你不能用普通gdb做的是修改內(nèi)核數(shù)據(jù);由于調(diào)試器需要在訪問內(nèi)存鏡象前運行被調(diào)試程<BR>序,它是不會去修改內(nèi)存鏡象文件的。當(dāng)調(diào)試內(nèi)核鏡象時,執(zhí)行run命令會導(dǎo)致在執(zhí)行若<BR>干指令后導(dǎo)致段違例。出于這個原因,/proc/kcore都沒有實現(xiàn)write方法。<BR> <BR>如果你用調(diào)試選項(-g)編譯了內(nèi)核,結(jié)果產(chǎn)生的vmlinux比沒有用-g選項的更適合于gd<BR>b。不過要注意,用-g選項編譯內(nèi)核需要大量的磁盤空間――支持網(wǎng)絡(luò)和很少幾個設(shè)備和<BR>文件系統(tǒng)的2.0內(nèi)核在PC上需要11KB。不過不管怎樣,你都可以生成zImage文件并用它來<BR>其他系統(tǒng):在生成可啟動鏡象時由于選項-g而加入的調(diào)試信息最終都被去掉了。如果我<BR>有足夠的磁盤空間,我會一致打開-g選項的。<BR> <BR>在非PC計算機上則有不同的方法。在Alpha上,make boot會在生成可啟動鏡象前將調(diào)試<BR>信息去掉,所以你最終會獲得vmlinux和vmlinux.gz兩個文件。gdb可以使用前者,但你<BR>只能用后者啟動。在Sparc上,默認情況下內(nèi)核(至少是2.0內(nèi)核)不會被去掉調(diào)試信息<BR>,所以你需要在將其傳遞給silo(Sparc的內(nèi)核加載器)前將調(diào)試信息去掉,這樣才能啟<BR></P></FONT><FONT
color=#ffffff size=3>
<P>,所以你需要在將其傳遞給silo(Sparc的內(nèi)核加載器)前將調(diào)試信息去掉,這樣才能啟<BR>動。由于尺寸的問題,無論milo(Alpha的內(nèi)核加載器)還是silo都不能啟動未去掉調(diào)試<BR>信息的內(nèi)核。<BR> <BR>當(dāng)你用-g選項編譯內(nèi)核并且用vmlinux和/proc/kcore一起使用調(diào)試器,gdb可以返回很多<BR>有關(guān)內(nèi)核內(nèi)部結(jié)構(gòu)的信息。例如,你可以使用類似于這樣的命令,p *module_list,p<BR>*module_list->next和p *chrdevs[4]->fops等顯示這些結(jié)構(gòu)的內(nèi)容。如果你手頭有內(nèi)核<BR>映射表和源碼的話,這些探測命令是非常有用的。<BR> <BR>另一個gdb可以在當(dāng)前內(nèi)核上執(zhí)行的有用任務(wù)是,通過disassemble命令(它可以縮寫)<BR>或是“檢查指令”(x/i)命令反匯編函數(shù)。disassemble命令的參數(shù)可以是函數(shù)名或是<BR>內(nèi)存區(qū)范圍,而x/i則使用一個內(nèi)存地址做為參數(shù),也可以用符號名。例如,你可以用x/<BR>20i反匯編20條指令。注意,你不能反匯編一個模塊的函數(shù),這是因為調(diào)試器處理vmlinu<BR>x,它并不知道你的模塊的信息。如果你試圖用模塊的地址反匯編代碼,gdb很有可能會<BR>報告“不能訪問xxxx處的內(nèi)存(Cannot access memory at xxxx)”。基于同樣的原因<BR>,你不查看屬于模塊的數(shù)據(jù)項。如果你知道你的變量的地址,你可以從/dev/mem中讀出<BR>它的值,但很難弄明白從系統(tǒng)內(nèi)存中分解出的數(shù)據(jù)是什么含義。<BR> <BR>如果你需要反匯編模塊函數(shù),你最好對用objdump工具處理你的模塊文件。很不幸,該工<BR>具只能對磁盤上的文件進行處理,而不能對運行中的模塊進行處理;因此,objdump中給<BR>出的地址都是未經(jīng)重定位的地<BR>--<BR> <BR></P></FONT><FONT
color=#ffffff size=3>
<P>或是“檢查指令”(x/i)命令反匯編函數(shù)。disassemble命令的參數(shù)可以是函數(shù)名或是<BR>內(nèi)存區(qū)范圍,而x/i則使用一個內(nèi)存地址做為參數(shù),也可以用符號名。例如,你可以用x/<BR>20i反匯編20條指令。注意,你不能反匯編一個模塊的函數(shù),這是因為調(diào)試器處理vmlinu<BR>x,它并不知道你的模塊的信息。如果你試圖用模塊的地址反匯編代碼,gdb很有可能會<BR>報告“不能訪問xxxx處的內(nèi)存(Cannot access memory at xxxx)”。基于同樣的原因<BR>,你不查看屬于模塊的數(shù)據(jù)項。如果你知道你的變量的地址,你可以從/dev/mem中讀出<BR>它的值,但很難弄明白從系統(tǒng)內(nèi)存中分解出的數(shù)據(jù)是什么含義。<BR> <BR>如果你需要反匯編模塊函數(shù),你最好對用objdump工具處理你的模塊文件。很不幸,該工<BR>具只能對磁盤上的文件進行處理,而不能對運行中的模塊進行處理;因此,objdump中給<BR>出的地址都是未經(jīng)重定位的地<BR>--<BR><FONT
color=#00ff00>※ 來源:.華南網(wǎng)木棉站 bbs.gznet.edu.cn.[FROM: 202.38.196.234]</FONT><BR>--<BR><FONT
color=#00ffff>※ 轉(zhuǎn)寄:.華南網(wǎng)木棉站 bbs.gznet.edu.cn.[FROM: 211.80.41.106]</FONT><BR>--<BR><FONT
color=#0000ff>※ 轉(zhuǎn)寄:.華南網(wǎng)木棉站 bbs.gznet.edu.cn.[FROM: 211.80.41.106]</FONT><BR>--<BR><FONT
color=#ffff00>※ 轉(zhuǎn)載:.南京大學(xué)小百合站 bbs.nju.edu.cn.[FROM: 211.80.41.106]</FONT><BR>--<BR><FONT
color=#ff0000>※ 轉(zhuǎn)載:·飲水思源 bbs.sjtu.edu.cn·[FROM: 211.80.41.106]</FONT><BR></P></FONT>
<P align=center><A href="http://joyfire.net/lsdp/index.htm"><FONT
color=#ffffff size=2>目錄頁</FONT></A> | <A
href="http://joyfire.net/lsdp/5.htm"><FONT color=#ffffff
size=2>上一頁</FONT></A> | <A href="http://joyfire.net/lsdp/7.htm"><FONT
color=#ffffff size=2>下一頁</FONT></A></P></SPAN></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="90%" align=center border=0>
<TBODY>
<TR>
<TD colSpan=3 height=2>
<TABLE cellSpacing=0 cellPadding=0 width="100%" bgColor=#666666
border=0><TBODY>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -