資源描述:
《linux調(diào)試技術(shù)介紹》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在行業(yè)資料-天天文庫(kù)。
1、Linux調(diào)試技術(shù)介紹Linux調(diào)試技術(shù)介紹對(duì)于任何編寫內(nèi)核代碼的人來(lái)說(shuō),最吸引他們注意的問(wèn)題之一就是如何完成調(diào)試。由于內(nèi)核是一個(gè)不與某個(gè)進(jìn)程相關(guān)的功能集,其代碼不能很輕松地放在調(diào)試器中執(zhí)行,而且也不能跟蹤。本章介紹你可以用來(lái)監(jiān)視內(nèi)核代碼和跟蹤錯(cuò)誤的技術(shù)。用打印信息調(diào)試最一般的調(diào)試技術(shù)就是監(jiān)視,就是在應(yīng)用內(nèi)部合適的點(diǎn)加上printf調(diào)用。當(dāng)你調(diào)試內(nèi)核代碼的時(shí)候,你可以用printk完成這個(gè)任務(wù)。Printk在前些章中,我們簡(jiǎn)單假設(shè)printk工作起來(lái)和printf很類似?,F(xiàn)在是介紹一下它們之間不同的時(shí)候了。其中一個(gè)不同點(diǎn)就是,printk允許你根據(jù)它們的嚴(yán)重程度,通過(guò)附加不同的“記錄級(jí)
2、”來(lái)對(duì)消息分類,或賦予消息優(yōu)先級(jí)。你可以用宏來(lái)指示記錄級(jí)。例如,KERN_INFO,我們前面已經(jīng)看到它被加在打印語(yǔ)句的前面,它就是一種可能的消息記錄級(jí)。記錄級(jí)宏展開為一個(gè)字串,在編譯時(shí)和消息文本拼接在一起;這也就是為什么下面的例子中優(yōu)先級(jí)和格式字串間沒(méi)有逗號(hào)。這有兩個(gè)printk的例子,一個(gè)是調(diào)試信息,一個(gè)是關(guān)鍵信息:(代碼)在中定義了8種記錄級(jí)別串。沒(méi)有指定優(yōu)先級(jí)的printk語(yǔ)句默認(rèn)使用DEFAULT_MESSAGE_LOGLEVEL優(yōu)先級(jí),它是一個(gè)在kernel/printk.c中定義的整數(shù)。默認(rèn)記錄級(jí)的具體數(shù)值在Linux的開發(fā)期間曾變化過(guò)若干次
3、,所以我建議你最好總是指定一個(gè)合適的記錄級(jí)。根據(jù)記錄級(jí),內(nèi)核將消息打印到當(dāng)前文本控制臺(tái)上:如果優(yōu)先級(jí)低于console_loglevel這個(gè)數(shù)值的話,該消息就顯示在控制臺(tái)上。如果系統(tǒng)同時(shí)運(yùn)行了klogd和syslogd,無(wú)論console_loglevel為何值,內(nèi)核都將消息追加到/var/log/messages中。變量console_loglevel最初初始化為DEFAULT_CONSOLE_LOGLEVEL,但可以通過(guò)sys_syslog系統(tǒng)調(diào)用修改。如klogd的手冊(cè)所示,可以在啟動(dòng)klogd時(shí)指定-c開關(guān)來(lái)修改這個(gè)變量。此外,你還可以寫個(gè)程序來(lái)改變控制臺(tái)記錄級(jí)。你可以在O’R
4、eilly站點(diǎn)上的源文件中找到我寫的一個(gè)這種功能的程序,miscprogs/setlevel.c。新優(yōu)先級(jí)是通過(guò)一個(gè)1到8之間的整數(shù)值指定的。你也許需要在內(nèi)核失效后降低記錄級(jí)(見“調(diào)試系統(tǒng)故障”),這是因?yàn)槭幚泶a會(huì)將console_loglevel提升到15,之后所有的消息都會(huì)出現(xiàn)在控制臺(tái)上。為看到你的調(diào)試信息,如果你運(yùn)行的是內(nèi)核2.0.x話,你需要提升記錄級(jí)。內(nèi)核2.0發(fā)行降低了MINIMUM_CONSOLE_LOGLEVEL,而舊版本的klogd默認(rèn)情況下要打印很多控制消息。如果你碰巧使用了這個(gè)舊版本的守護(hù)進(jìn)程,除非你提升記錄級(jí),內(nèi)核2.0會(huì)比你預(yù)期的打印出更少的消息。這就是
5、為什么hello.c中使用了<1>標(biāo)記,這樣可以保證消息顯示在控制臺(tái)上。從1.3.43一來(lái)的內(nèi)核版本通過(guò)允許你向指定虛控制臺(tái)發(fā)送消息,藉此提供一個(gè)靈活的記錄策略。默認(rèn)情況下,“控制臺(tái)”是當(dāng)前虛終端。也可以選擇不同的虛終端接收消息,你只需向所選的虛終端調(diào)用ioctl(TIOCLINUX)。如下程序,setconsole,可以用來(lái)選擇哪個(gè)虛終端接收內(nèi)核消息;它必須以超級(jí)用戶身份運(yùn)行。如果你對(duì)ioctl還不有把握,你可以跳過(guò)這至下一節(jié),等到讀完第5章“字符設(shè)備驅(qū)動(dòng)程序的擴(kuò)展操作”的“ioctl”一節(jié)后,再回到這里讀這段代碼。(代碼)setconsole使用了用于Linux專用功能的特殊的io
6、ctl命令TIOCLINUX。為了使用TIOCLINUX,你要傳遞給它一個(gè)指向字節(jié)數(shù)組的指針。數(shù)組的第一個(gè)字節(jié)是所請(qǐng)求的子命令的編碼,隨后的字節(jié)依命令而不同。在setconsole中使用了子命令11,后一個(gè)字節(jié)(存放在bytes[1]中)標(biāo)別虛擬控制臺(tái)。TIOCLINUX的完成介紹可以在內(nèi)核源碼drivers/char/tty_io.c中找到。消息是如何記錄的printk函數(shù)將消息寫到一個(gè)長(zhǎng)度為L(zhǎng)OG_BUF_LEN個(gè)字節(jié)的循環(huán)緩沖區(qū)中。然后喚醒任何等待消息的進(jìn)程,即那些在調(diào)用syslog系統(tǒng)調(diào)用或讀取/proc/kmesg過(guò)程中睡眠的進(jìn)程。這兩個(gè)訪問(wèn)記錄引擎的接口是等價(jià)的。不過(guò)/pr
7、oc/kmesg文件更象一個(gè)FIFO文件,從中讀取數(shù)據(jù)更容易些。一條簡(jiǎn)單的cat命令就可以讀取消息。如果循環(huán)緩沖區(qū)填滿了,printk就繞到緩沖區(qū)的開始處填寫新數(shù)據(jù),覆蓋舊數(shù)據(jù)。于是記錄進(jìn)程就丟失了最舊的數(shù)據(jù)。這個(gè)問(wèn)題與利用循環(huán)緩沖區(qū)所獲得的好處相比可以忽略不計(jì)。例如,循環(huán)緩沖區(qū)可以使系統(tǒng)在沒(méi)有記錄進(jìn)程的情況下照樣運(yùn)行,同時(shí)又不浪費(fèi)內(nèi)存。Linux處理消息的方法的另一個(gè)特點(diǎn)是,可以在任何地方調(diào)用printk,甚至在中斷處理函數(shù)里也可以調(diào)用,而且