




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、1第第4 章章 調(diào)試技術(shù)調(diào)試技術(shù)內(nèi)核中的調(diào)試支持內(nèi)核中的調(diào)試支持 通過(guò)打印調(diào)試通過(guò)打印調(diào)試 通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試 通過(guò)監(jiān)視調(diào)試通過(guò)監(jiān)視調(diào)試 調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障 調(diào)試器和相關(guān)工具調(diào)試器和相關(guān)工具2內(nèi)核中的調(diào)試支持內(nèi)核中的調(diào)試支持l內(nèi)核開(kāi)發(fā)者建立了許多用于支持調(diào)試的功能,以方便調(diào)試,內(nèi)核開(kāi)發(fā)者建立了許多用于支持調(diào)試的功能,以方便調(diào)試,但這些功能會(huì)導(dǎo)致性能下降,發(fā)行版自帶內(nèi)核中往往關(guān)閉了但這些功能會(huì)導(dǎo)致性能下降,發(fā)行版自帶內(nèi)核中往往關(guān)閉了這些功能這些功能l內(nèi)核開(kāi)發(fā)者需要這些功能,應(yīng)該打開(kāi)這些調(diào)試功能內(nèi)核開(kāi)發(fā)者需要這些功能,應(yīng)該打開(kāi)這些調(diào)試功能l重新配置、編譯、安裝內(nèi)核重新配置、編譯、安裝內(nèi)
2、核lKernel hacking菜單中有如下選項(xiàng)菜單中有如下選項(xiàng)CONFIG_DEBUG_KERNEL 調(diào)試選項(xiàng)總開(kāi)關(guān),關(guān)時(shí)全關(guān),開(kāi)時(shí)并不打開(kāi)下級(jí)子開(kāi)關(guān)調(diào)試選項(xiàng)總開(kāi)關(guān),關(guān)時(shí)全關(guān),開(kāi)時(shí)并不打開(kāi)下級(jí)子開(kāi)關(guān)CONFIG_DEBUG_SLAB 開(kāi)啟內(nèi)存分配函數(shù)中的類(lèi)型檢查,可以檢測(cè)內(nèi)存溢出及開(kāi)啟內(nèi)存分配函數(shù)中的類(lèi)型檢查,可以檢測(cè)內(nèi)存溢出及忘記初始化錯(cuò)誤忘記初始化錯(cuò)誤3內(nèi)核中的調(diào)試支持內(nèi)核中的調(diào)試支持CONFIG_DEBUG_PAGEALLOC 該選項(xiàng)大降速度,但可定位特定內(nèi)存損壞錯(cuò)誤所在位置該選項(xiàng)大降速度,但可定位特定內(nèi)存損壞錯(cuò)誤所在位置CONFIG_DEBUG_SPINLOCK 內(nèi)核將捕獲未初始化自
3、旋鎖及兩次解開(kāi)同一鎖等錯(cuò)誤內(nèi)核將捕獲未初始化自旋鎖及兩次解開(kāi)同一鎖等錯(cuò)誤CONFIG_DEBUG_SPINLOCK_SLEEP 檢查擁有自旋鎖時(shí)的休眠企圖檢查擁有自旋鎖時(shí)的休眠企圖CONFIG_INIT_DEBUG 用于初始化完成后對(duì)用于初始化的內(nèi)存空間的訪(fǎng)問(wèn)檢查用于初始化完成后對(duì)用于初始化的內(nèi)存空間的訪(fǎng)問(wèn)檢查CONFIG_DEBUG_INFO 使內(nèi)核的構(gòu)造包含完整的調(diào)試信息,使內(nèi)核的構(gòu)造包含完整的調(diào)試信息,gdb需要需要4內(nèi)核中的調(diào)試支持內(nèi)核中的調(diào)試支持CONFIG_MAGIC_SYSRQ 打開(kāi)打開(kāi)“SYsRq魔法魔法”按鍵按鍵CONFIG_DEBUG_STACKOVERFLOWCONFIG
4、_DEBUG_STACK_USAGE 幫助跟蹤內(nèi)核棧溢出問(wèn)題,前者在內(nèi)核中增加明確有溢幫助跟蹤內(nèi)核棧溢出問(wèn)題,前者在內(nèi)核中增加明確有溢出檢查,后者讓內(nèi)核監(jiān)視棧的使用,出檢查,后者讓內(nèi)核監(jiān)視棧的使用, 并通過(guò)并通過(guò)SYsRq按按鍵輸出一些統(tǒng)計(jì)信息鍵輸出一些統(tǒng)計(jì)信息lCONFIG_KALLSYMS出現(xiàn)在出現(xiàn)在General setup/Standard features菜單中菜單中內(nèi)核中包含用于調(diào)試上下文的符號(hào)信息內(nèi)核中包含用于調(diào)試上下文的符號(hào)信息5內(nèi)核中的調(diào)試支持內(nèi)核中的調(diào)試支持lCONFIG_IKCONFIGlCONFIG_IKCONFIG_PROC出現(xiàn)在出現(xiàn)在General setup菜單中
5、菜單中讓完整的內(nèi)核配置狀態(tài)包含到內(nèi)核中,并可通過(guò)讓完整的內(nèi)核配置狀態(tài)包含到內(nèi)核中,并可通過(guò)/proc訪(fǎng)問(wèn)訪(fǎng)問(wèn)lCONFIG_ACPI_DEBUG出現(xiàn)在出現(xiàn)在Power management/ACPI菜單中菜單中打開(kāi)打開(kāi)ACPI(Advanced Configuration and Power Interface)中中的詳細(xì)調(diào)試信息,若疑遇到問(wèn)題與的詳細(xì)調(diào)試信息,若疑遇到問(wèn)題與ACPI相關(guān)時(shí)用相關(guān)時(shí)用lCONFIG_DEBUG_DRIVER出現(xiàn)在出現(xiàn)在Device drivers菜單中菜單中打開(kāi)驅(qū)動(dòng)程序核心中的調(diào)試信息,可以幫助跟蹤底層支持代碼中打開(kāi)驅(qū)動(dòng)程序核心中的調(diào)試信息,可以幫助跟蹤底層支持
6、代碼中的問(wèn)題的問(wèn)題6內(nèi)核中的調(diào)試支持內(nèi)核中的調(diào)試支持lCONFIG_SCSI_CONSTANTS出現(xiàn)在出現(xiàn)在Device drivers/SCSI device support菜單中菜單中打開(kāi)詳細(xì)的打開(kāi)詳細(xì)的SCSI錯(cuò)誤消息,開(kāi)發(fā)錯(cuò)誤消息,開(kāi)發(fā)SCSI驅(qū)動(dòng)時(shí)可用驅(qū)動(dòng)時(shí)可用lCONFIG_INPUT_EVBUG出現(xiàn)在出現(xiàn)在Device drivers/Input device support菜單中菜單中打開(kāi)對(duì)輸入事件的詳細(xì)記錄,開(kāi)發(fā)輸入設(shè)備驅(qū)動(dòng)時(shí)可用打開(kāi)對(duì)輸入事件的詳細(xì)記錄,開(kāi)發(fā)輸入設(shè)備驅(qū)動(dòng)時(shí)可用lCONFIG_PROFILING出現(xiàn)在出現(xiàn)在Profiling support菜單中菜單中用于系統(tǒng)
7、性能的調(diào)節(jié),但對(duì)跟蹤內(nèi)核掛起及相關(guān)問(wèn)題也有幫助用于系統(tǒng)性能的調(diào)節(jié),但對(duì)跟蹤內(nèi)核掛起及相關(guān)問(wèn)題也有幫助7第第4 章章 調(diào)試技術(shù)調(diào)試技術(shù)內(nèi)核中的調(diào)試支持內(nèi)核中的調(diào)試支持 通過(guò)打印調(diào)試通過(guò)打印調(diào)試 通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試 通過(guò)監(jiān)視調(diào)試通過(guò)監(jiān)視調(diào)試 調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障 調(diào)試器和相關(guān)工具調(diào)試器和相關(guān)工具8通過(guò)打印調(diào)試通過(guò)打印調(diào)試lPrintk是內(nèi)核調(diào)試中最簡(jiǎn)單有效的工具,通過(guò)在內(nèi)核是內(nèi)核調(diào)試中最簡(jiǎn)單有效的工具,通過(guò)在內(nèi)核代碼的某些關(guān)鍵地方放置一條代碼的某些關(guān)鍵地方放置一條printk語(yǔ)句,打印一些語(yǔ)句,打印一些信息,即可知道運(yùn)行代碼的某些行為,例:信息,即可知道運(yùn)行代碼的某些行為,例: prin
8、tk(KERN_CRIT Im trashed; giving up on %pn, ptr);lPrintk的使用需要包含頭文件的使用需要包含頭文件l只有在消息優(yōu)先級(jí)高于控制臺(tái)優(yōu)先級(jí)時(shí),信息才能出只有在消息優(yōu)先級(jí)高于控制臺(tái)優(yōu)先級(jí)時(shí),信息才能出現(xiàn)在終端上現(xiàn)在終端上l控制臺(tái)日志級(jí)別控制臺(tái)日志級(jí)別console_loglevel的初始值為的初始值為DEFAULT_CONSOLE_LOGLEVE,可通過(guò)可通過(guò)sys_syslog系統(tǒng)調(diào)用修改,也可通過(guò)文本文件系統(tǒng)調(diào)用修改,也可通過(guò)文本文件/proc/sys/kernel/printk修改修改9通過(guò)打印調(diào)試通過(guò)打印調(diào)試l例例 如下指令將控制臺(tái)日志級(jí)別修
9、改為如下指令將控制臺(tái)日志級(jí)別修改為8 # echo 8 /proc/sys/kernel/printkl下表為消息日志級(jí)別,數(shù)字越小,優(yōu)先級(jí)越高下表為消息日志級(jí)別,數(shù)字越小,優(yōu)先級(jí)越高 日志級(jí)別日志級(jí)別 描述描述 KERN_EMERG 緊急事件消息緊急事件消息 KERN_ALERT 用于需要立即采取動(dòng)作的情況用于需要立即采取動(dòng)作的情況 KERN_CRIT 臨界狀態(tài),通常涉及嚴(yán)重的硬件或軟件操作失敗臨界狀態(tài),通常涉及嚴(yán)重的硬件或軟件操作失敗 KERN_ERR 用于報(bào)告錯(cuò)誤狀態(tài)用于報(bào)告錯(cuò)誤狀態(tài) KERN_WARNING 對(duì)可能出現(xiàn)問(wèn)題的情況進(jìn)行警告對(duì)可能出現(xiàn)問(wèn)題的情況進(jìn)行警告 KERN_NOTIC
10、E 有必要進(jìn)行提示的情形有必要進(jìn)行提示的情形 KERN_INFO 提示性信息提示性信息 KERN_DEBUG 用于調(diào)試信息用于調(diào)試信息10通過(guò)打印調(diào)試通過(guò)打印調(diào)試l未指定消息優(yōu)先級(jí)的未指定消息優(yōu)先級(jí)的 printk 語(yǔ)句缺省優(yōu)先級(jí)是語(yǔ)句缺省優(yōu)先級(jí)是 DEFAULT_MESSAGE_LOGLEVEL, 在在 kernel/printk.c 里指定作為一個(gè)整數(shù)里指定作為一個(gè)整數(shù). 在在 2.6.10 內(nèi)核內(nèi)核中中, 為為 KERN_WARNING。11通過(guò)打印調(diào)試通過(guò)打印調(diào)試l消息如何被記錄消息如何被記錄printk將消息寫(xiě)到一個(gè)長(zhǎng)度為將消息寫(xiě)到一個(gè)長(zhǎng)度為_(kāi)LOG_BUF_LEN(4KB1MB,默
11、認(rèn),默認(rèn)16KB)的循環(huán)緩沖區(qū)的循環(huán)緩沖區(qū)中中,然后喚醒在該緩沖區(qū)上等待消息的進(jìn)程然后喚醒在該緩沖區(qū)上等待消息的進(jìn)程 睡眠在睡眠在syslog系統(tǒng)調(diào)用上的進(jìn)程系統(tǒng)調(diào)用上的進(jìn)程(調(diào)用調(diào)用syslog()-寫(xiě)、寫(xiě)、openlog()-打打開(kāi)或開(kāi)或closelog()-關(guān)閉的進(jìn)程關(guān)閉的進(jìn)程) 正在讀取文件正在讀取文件/proc/kmsg的進(jìn)程的進(jìn)程用戶(hù)空間守護(hù)進(jìn)程用戶(hù)空間守護(hù)進(jìn)程klogd運(yùn)行時(shí)讀取內(nèi)核消息(通過(guò)運(yùn)行時(shí)讀取內(nèi)核消息(通過(guò)syslog系統(tǒng)調(diào)用或系統(tǒng)調(diào)用或/proc/dmsg文件,默認(rèn)為后者),并傳文件,默認(rèn)為后者),并傳給另一個(gè)守護(hù)進(jìn)程給另一個(gè)守護(hù)進(jìn)程syslogdsyslogd根據(jù)根
12、據(jù)/etc/syslog.conf設(shè)置的處理方法處理收到的設(shè)置的處理方法處理收到的消息,默認(rèn)追加到消息,默認(rèn)追加到/var/log/message中中klogd也可將消息存入一指定文件中,不給也可將消息存入一指定文件中,不給syslogd12通過(guò)打印調(diào)試通過(guò)打印調(diào)試l若若klogd沒(méi)運(yùn)行,消息不會(huì)送到用戶(hù)空間,只能查看沒(méi)運(yùn)行,消息不會(huì)送到用戶(hù)空間,只能查看/proc/kmsg文件(可通過(guò)文件(可通過(guò)dmesg命令)命令)13通過(guò)打印調(diào)試通過(guò)打印調(diào)試l開(kāi)啟及關(guān)閉消息開(kāi)啟及關(guān)閉消息printk對(duì)調(diào)試和測(cè)試新代碼很有幫助,但在正式發(fā)布驅(qū)動(dòng)對(duì)調(diào)試和測(cè)試新代碼很有幫助,但在正式發(fā)布驅(qū)動(dòng)程序時(shí),就需要?jiǎng)h除
13、或禁用程序時(shí),就需要?jiǎng)h除或禁用如何有效地啟用如何有效地啟用/禁用它們?禁用它們?#undef PDEBUG #ifdef SCULL_DEBUG# ifdef _KERNEL_# define PDEBUG(fmt, args.) printk( KERN_DEBUG scull: fmt, # args)# else # define PDEBUG(fmt, args.) fprintf(stderr, fmt, # args)# endif#else# define PDEBUG(fmt, args.) #endif#undef PDEBUGG#define PDEBUGG(fmt, ar
14、gs.)14通過(guò)打印調(diào)試通過(guò)打印調(diào)試l打印速度控制打印速度控制Printk有時(shí)每秒鐘能產(chǎn)生上萬(wàn)條消息充滿(mǎn)控制臺(tái)或使有時(shí)每秒鐘能產(chǎn)生上萬(wàn)條消息充滿(mǎn)控制臺(tái)或使日志文件溢出,若控制臺(tái)為串口超級(jí)終端,過(guò)高的消日志文件溢出,若控制臺(tái)為串口超級(jí)終端,過(guò)高的消息輸出速度會(huì)使系統(tǒng)變慢,甚至無(wú)法正常響應(yīng)。息輸出速度會(huì)使系統(tǒng)變慢,甚至無(wú)法正常響應(yīng)。內(nèi)核提供了控制打印速度的函數(shù),原型為:內(nèi)核提供了控制打印速度的函數(shù),原型為: int printk_ratelimit(void);可通過(guò)函數(shù)的返回值來(lái)控制打印輸出,若函數(shù)返回一可通過(guò)函數(shù)的返回值來(lái)控制打印輸出,若函數(shù)返回一個(gè)非零值,繼續(xù)輸出消息,否則跳過(guò),例:個(gè)非零值
15、,繼續(xù)輸出消息,否則跳過(guò),例: if (printk_ratelimit( ) printk(KERN_NOTICE The printer is still on firen);15通過(guò)打印調(diào)試通過(guò)打印調(diào)試printk_ratelimit跟蹤發(fā)送到控制臺(tái)的消息數(shù)量,若超跟蹤發(fā)送到控制臺(tái)的消息數(shù)量,若超過(guò)某一閾值,則返回過(guò)某一閾值,則返回0,否則非,否則非0可通過(guò)修改下列文件控制可通過(guò)修改下列文件控制printk_ratelimit的行為的行為 /proc/sys/kernel/printk_ratelimit /proc/sys/kernel/printk_ratelimit_burst16
16、通過(guò)打印調(diào)試通過(guò)打印調(diào)試l打印設(shè)備編號(hào)打印設(shè)備編號(hào)當(dāng)從一個(gè)驅(qū)動(dòng)程序打印消息時(shí),有時(shí)會(huì)希望打印關(guān)聯(lián)當(dāng)從一個(gè)驅(qū)動(dòng)程序打印消息時(shí),有時(shí)會(huì)希望打印關(guān)聯(lián)的設(shè)備編號(hào),內(nèi)核提供了兩個(gè)宏:的設(shè)備編號(hào),內(nèi)核提供了兩個(gè)宏:int print_dev_t(char *buffer, dev_t dev);char *format_dev_t(char *buffer, dev_t dev);17第第4 章章 調(diào)試技術(shù)調(diào)試技術(shù)內(nèi)核中的調(diào)試支持內(nèi)核中的調(diào)試支持 通過(guò)打印調(diào)試通過(guò)打印調(diào)試 通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試 通過(guò)監(jiān)視調(diào)試通過(guò)監(jiān)視調(diào)試 調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障 調(diào)試器和相關(guān)工具調(diào)試器和相關(guān)工具18通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)
17、調(diào)試l通過(guò)打印調(diào)試的缺點(diǎn)通過(guò)打印調(diào)試的缺點(diǎn)syslogd會(huì)一直保持對(duì)其輸出文件的同步刷新,降低性會(huì)一直保持對(duì)其輸出文件的同步刷新,降低性能。雖可通過(guò)在能。雖可通過(guò)在/etc/syslog.conf中日志文件的名字前中日志文件的名字前加一減號(hào)前綴來(lái)避免,但調(diào)試完后配置會(huì)被保留下來(lái)加一減號(hào)前綴來(lái)避免,但調(diào)試完后配置會(huì)被保留下來(lái)雖可通過(guò)降低雖可通過(guò)降低console_loglevel來(lái)減少控制臺(tái)輸出,但來(lái)減少控制臺(tái)輸出,但大量大量printk的使用也降低性能的使用也降低性能l大多數(shù)情況下,獲取相關(guān)信息的最好方法是在需要的大多數(shù)情況下,獲取相關(guān)信息的最好方法是在需要的時(shí)候才去查詢(xún),而不是持續(xù)不斷地產(chǎn)生
18、數(shù)據(jù),如時(shí)候才去查詢(xún),而不是持續(xù)不斷地產(chǎn)生數(shù)據(jù),如ps、netstat、vmstat等等l驅(qū)動(dòng)程序開(kāi)發(fā)中可用的查詢(xún)方法有驅(qū)動(dòng)程序開(kāi)發(fā)中可用的查詢(xún)方法有在在/proc中創(chuàng)建文件、中創(chuàng)建文件、ioctl方法、方法、sysfs等等19通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試1. /proc文件系統(tǒng)文件系統(tǒng)/proc文件系統(tǒng)是一種讀時(shí)創(chuàng)建的文件系統(tǒng)是一種讀時(shí)創(chuàng)建的“內(nèi)存文件系統(tǒng)內(nèi)存文件系統(tǒng)”。每個(gè)文件都綁定一個(gè)內(nèi)核函數(shù),當(dāng)文件被讀取時(shí),該每個(gè)文件都綁定一個(gè)內(nèi)核函數(shù),當(dāng)文件被讀取時(shí),該函數(shù)動(dòng)態(tài)地生成文件的函數(shù)動(dòng)態(tài)地生成文件的“內(nèi)容內(nèi)容”內(nèi)核使用內(nèi)核使用/proc文件系統(tǒng)向外界導(dǎo)出信息,如文件系統(tǒng)向外界導(dǎo)出信息,如/pr
19、oc/modules因此可通過(guò)因此可通過(guò)/proc文件系統(tǒng)將設(shè)備信息導(dǎo)出到用戶(hù)空間文件系統(tǒng)將設(shè)備信息導(dǎo)出到用戶(hù)空間,以方便對(duì)設(shè)備驅(qū)動(dòng)程序進(jìn)行調(diào)試,以方便對(duì)設(shè)備驅(qū)動(dòng)程序進(jìn)行調(diào)試l在在/proc中實(shí)現(xiàn)文件系統(tǒng)需做兩件事中實(shí)現(xiàn)文件系統(tǒng)需做兩件事創(chuàng)建一個(gè)函數(shù),用于在文件被讀取時(shí)生成文件數(shù)據(jù)創(chuàng)建一個(gè)函數(shù),用于在文件被讀取時(shí)生成文件數(shù)據(jù)創(chuàng)建文件節(jié)點(diǎn)創(chuàng)建文件節(jié)點(diǎn)20通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試l創(chuàng)建函數(shù)創(chuàng)建函數(shù)當(dāng)一個(gè)進(jìn)程讀取當(dāng)一個(gè)進(jìn)程讀取 /proc 文件時(shí)文件時(shí), 內(nèi)核會(huì)分配一頁(yè)內(nèi)存,內(nèi)核會(huì)分配一頁(yè)內(nèi)存,我們可以把設(shè)備數(shù)據(jù)寫(xiě)入其中,以返回給用戶(hù)空間。我們可以把設(shè)備數(shù)據(jù)寫(xiě)入其中,以返回給用戶(hù)空間。 那個(gè)將數(shù)據(jù)寫(xiě)
20、入這個(gè)緩存區(qū)的函數(shù)那個(gè)將數(shù)據(jù)寫(xiě)入這個(gè)緩存區(qū)的函數(shù), 就是我們要?jiǎng)?chuàng)建的就是我們要?jiǎng)?chuàng)建的函數(shù),稱(chēng)為函數(shù),稱(chēng)為 read_proc 方法,函數(shù)原型如下:方法,函數(shù)原型如下:int (*read_proc)(char *page, char *start, off_t offset, int count, int *eof, void *data); page:指向用來(lái)寫(xiě)入數(shù)據(jù)的緩沖區(qū),大小為一頁(yè)指向用來(lái)寫(xiě)入數(shù)據(jù)的緩沖區(qū),大小為一頁(yè) start:指向數(shù)據(jù)寫(xiě)入頁(yè)中的具體位置指向數(shù)據(jù)寫(xiě)入頁(yè)中的具體位置 offset:相對(duì)于頁(yè)邊界的偏移量相對(duì)于頁(yè)邊界的偏移量 count:寫(xiě)入的字節(jié)數(shù)寫(xiě)入的字節(jié)數(shù) eof:指
21、向一個(gè)整型數(shù)的指針,可返回一個(gè)整型數(shù)指向一個(gè)整型數(shù)的指針,可返回一個(gè)整型數(shù) data:提供給驅(qū)動(dòng)程序的專(zhuān)用數(shù)據(jù)指針:提供給驅(qū)動(dòng)程序的專(zhuān)用數(shù)據(jù)指針21通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試scull中的實(shí)現(xiàn)中的實(shí)現(xiàn)int scull_read_procmem(char *buf, char *start, off_t offset, int count, int *eof, void *data) int i, j, len = 0; int limit = count - 80; for (i = 0; i scull_nr_devs & len data; if (down_interruptib
22、le(&d-sem) return -ERESTARTSYS; len += sprintf(buf+len,nDevice %i: qset %i, q %i, sz %lin, i, d-qset, d-quantum, d-size); for (; qs & len next) len += sprintf(buf + len, item at %p, qset at %pn, qs, qs-data); if (qs-data & !qs-next) for (j = 0; j qset; j+) if (qs-dataj) len += sprintf(bu
23、f + len, % 4i: %8pn, j, qs-dataj); up(&scull_devicesi.sem); *eof = 1; return len;22通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試l創(chuàng)建創(chuàng)建/proc文件節(jié)點(diǎn)文件節(jié)點(diǎn)原型原型struct proc_dir_entry *create_proc_read_entry(const char *name, mode_t mode, struct proc_dir_entry *base, read_proc_t *read_proc, void *data); name:要?jiǎng)?chuàng)建的文件名要?jiǎng)?chuàng)建的文件名 mode:該文件的保護(hù)掩碼,該文
24、件的保護(hù)掩碼,0為系統(tǒng)默認(rèn)值(全局可讀)為系統(tǒng)默認(rèn)值(全局可讀) base:指定該文件所在的目錄,若為:指定該文件所在的目錄,若為NULL,則在,則在/proc的根目錄的根目錄 read_proc:實(shí)現(xiàn)該文件的:實(shí)現(xiàn)該文件的read_proc方法方法Scull中的實(shí)現(xiàn)中的實(shí)現(xiàn)create_proc_read_entry(scullmem, 0 , NULL ,scull_read_procmem,NULL );節(jié)點(diǎn)刪除節(jié)點(diǎn)刪除remove_proc_entry(scullmem, NULL /* parent dir */);23通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試2. seq_file接口接口在在/pr
25、oc中創(chuàng)建文件的另一種方式。在中創(chuàng)建文件的另一種方式。在/proc下創(chuàng)建的下創(chuàng)建的文件大小通常不超過(guò)一頁(yè),文件大小通常不超過(guò)一頁(yè),seq_file接口不受此限制接口不受此限制,且相當(dāng)靈活。,且相當(dāng)靈活。seq_file接口假定我們正在創(chuàng)建的虛擬文件要順序遍接口假定我們正在創(chuàng)建的虛擬文件要順序遍歷一個(gè)項(xiàng)目序列,而這些項(xiàng)目正是必須要返回給用戶(hù)歷一個(gè)項(xiàng)目序列,而這些項(xiàng)目正是必須要返回給用戶(hù)空間的空間的為使用為使用seq_file,我們必須創(chuàng)建一個(gè)簡(jiǎn)單的,我們必須創(chuàng)建一個(gè)簡(jiǎn)單的“迭代器迭代器(iterator)”對(duì)象,該對(duì)象用來(lái)表示項(xiàng)目系列中的位對(duì)象,該對(duì)象用來(lái)表示項(xiàng)目系列中的位置,每前進(jìn)一步,該對(duì)象
26、輸出序列中的一個(gè)項(xiàng)目置,每前進(jìn)一步,該對(duì)象輸出序列中的一個(gè)項(xiàng)目迭代器對(duì)象分別為迭代器對(duì)象分別為start、next、stop和和show24通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試Start方法首先被調(diào)用方法首先被調(diào)用,原型如下:原型如下:void *start(struct seq_file *sfile, loff_t *pos); sfile通常被忽略通常被忽略 pos表示讀取位置,為指向下一個(gè)項(xiàng)目的指針。表示讀取位置,為指向下一個(gè)項(xiàng)目的指針。scull 驅(qū)驅(qū)動(dòng)將每個(gè)設(shè)備作為系列中的一項(xiàng)動(dòng)將每個(gè)設(shè)備作為系列中的一項(xiàng), 因此因此pos 可作為可作為 scull_device 數(shù)組的索引。于是數(shù)組的索引。于
27、是, scull 使用的使用的 start 方方法如下:法如下: static void *scull_seq_start(struct seq_file *s, loff_t *pos) if (*pos = scull_nr_devs) return NULL; return scull_devices + *pos;25通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試next 函數(shù)應(yīng)當(dāng)將函數(shù)應(yīng)當(dāng)將iterator移動(dòng)到下一個(gè)位置移動(dòng)到下一個(gè)位置, 如果序如果序列里什么都沒(méi)有剩下就返回列里什么都沒(méi)有剩下就返回 NULL,這個(gè)方法的原,這個(gè)方法的原型是型是:void *next(struct seq_file *s
28、file, void *v, loff_t *pos); v 是先前對(duì)是先前對(duì) start 或者或者 next 調(diào)用所返回的調(diào)用所返回的 iterator, pos 是文件的當(dāng)前位置。是文件的當(dāng)前位置。next 應(yīng)當(dāng)遞增應(yīng)當(dāng)遞增 pos 指向的值,指向的值, scull 的的next方法實(shí)現(xiàn)如下方法實(shí)現(xiàn)如下: static void *scull_seq_next(struct seq_file *s, void *v, loff_t *pos) (*pos)+; if (*pos = scull_nr_devs) return NULL; return scull_devices + *po
29、s;26通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試當(dāng)內(nèi)核處理完當(dāng)內(nèi)核處理完 iterator之后之后, 會(huì)調(diào)用會(huì)調(diào)用 stop方法通知我們方法通知我們進(jìn)行清除工作,進(jìn)行清除工作,stop函數(shù)原型如下:函數(shù)原型如下:void stop(struct seq_file *sfile, void *v); scull 實(shí)現(xiàn)沒(méi)有清理工作要做實(shí)現(xiàn)沒(méi)有清理工作要做, 所以它的所以它的 stop 方法是空方法是空的的.在上述調(diào)用之間在上述調(diào)用之間, 內(nèi)核會(huì)調(diào)用內(nèi)核會(huì)調(diào)用 show 方法來(lái)將實(shí)際數(shù)據(jù)方法來(lái)將實(shí)際數(shù)據(jù)輸出到用戶(hù)空間輸出到用戶(hù)空間. 這個(gè)方法的原型是這個(gè)方法的原型是:int show(struct seq_file
30、 *sfile, void *v); 這個(gè)方法為這個(gè)方法為 iterator v 指向的項(xiàng)目建立輸出。但是,它指向的項(xiàng)目建立輸出。但是,它不能使用不能使用 printk, 應(yīng)該使用針對(duì)應(yīng)該使用針對(duì)seq_file的一套特殊函數(shù)的一套特殊函數(shù)27通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試int seq_printf(struct seq_file *sfile, const char *fmt, .);這是這是 seq_file 實(shí)現(xiàn)的實(shí)現(xiàn)的 printf等價(jià)等價(jià) 函數(shù)函數(shù); 它采用常用的它采用常用的格式串和附加值參數(shù)格式串和附加值參數(shù). 你必須將給你必須將給 show 函數(shù)的函數(shù)的 set_file 結(jié)構(gòu)傳遞給
31、它結(jié)構(gòu)傳遞給它Scull中的中的show方法實(shí)現(xiàn)如下:方法實(shí)現(xiàn)如下:28通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試static int scull_seq_show(struct seq_file *s, void *v) struct scull_dev *dev = (struct scull_dev *) v; struct scull_qset *d; int i; if (down_interruptible(&dev-sem) return -ERESTARTSYS; seq_printf(s, nDevice %i: qset %i, q %i, sz %lin, (int) (dev -
32、 scull_devices), dev-qset, dev-quantum, dev-size); for (d = dev-data; d; d = d-next) seq_printf(s, item at %p, qset at %pn, d, d-data); if (d-data & !d-next) for (i = 0; i qset; i+) if (d-datai) seq_printf(s, % 4i: %8pn, i, d-datai); up(&dev-sem); return 0;29通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試l上面已經(jīng)定義了完整的迭代器操作函數(shù),上面
33、已經(jīng)定義了完整的迭代器操作函數(shù),scull必須必須將這些函數(shù)打包并和將這些函數(shù)打包并和/proc中的某個(gè)文件連接起來(lái),中的某個(gè)文件連接起來(lái),首先要填沖一個(gè)首先要填沖一個(gè)seq_operations結(jié)構(gòu)體:結(jié)構(gòu)體:static struct seq_operations scull_seq_ops = .start = scull_seq_start, .next = scull_seq_next, .stop = scull_seq_stop, .show = scull_seq_show;30通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試l首先創(chuàng)建文件的首先創(chuàng)建文件的open方法,該方法將文件連接到方法,該方法將
34、文件連接到seq_file操作操作static int scull_proc_open(struct inode *inode, struct file *fil return seq_open(file, &scull_seq_ops);31通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試l對(duì)對(duì)seq_open的調(diào)用將的調(diào)用將file結(jié)構(gòu)和我們上面定義的序結(jié)構(gòu)和我們上面定義的序列操作連接在一起。事實(shí)上列操作連接在一起。事實(shí)上, open 是我們必須自己是我們必須自己實(shí)現(xiàn)的唯一文件操作實(shí)現(xiàn)的唯一文件操作, 因此我們現(xiàn)在可以建立我們的因此我們現(xiàn)在可以建立我們的 file_operations 結(jié)構(gòu)結(jié)構(gòu):stat
35、ic struct file_operations scull_proc_ops = .owner = THIS_MODULE, .open = scull_proc_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release;32通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試l建立建立/proc 文件節(jié)點(diǎn)文件節(jié)點(diǎn)函數(shù)原型函數(shù)原型struct proc_dir_entry *create_proc_entry(const char *name,mode_t mode, struct proc_dir_entry *parent); name
36、:要?jiǎng)?chuàng)建的文件名:要?jiǎng)?chuàng)建的文件名 mode:該文件的保護(hù)掩碼:該文件的保護(hù)掩碼 parent:父目錄:父目錄Scull中的實(shí)現(xiàn)中的實(shí)現(xiàn)entry = create_proc_entry(scullseq, 0, NULL);if (entry) entry-proc_fops = &scull_proc_ops;33通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試lioctl是一個(gè)作用于文件描述符上的系統(tǒng)調(diào)用是一個(gè)作用于文件描述符上的系統(tǒng)調(diào)用, 它接收它接收一個(gè)命令號(hào)以及一個(gè)命令號(hào)以及(可選地可選地)另一個(gè)參數(shù)另一個(gè)參數(shù), 常常是一個(gè)指常常是一個(gè)指針。針。 作為作為/proc 文件系統(tǒng)的替代文件系統(tǒng)的替代,
37、你可以實(shí)現(xiàn)幾個(gè)用你可以實(shí)現(xiàn)幾個(gè)用來(lái)調(diào)試用的來(lái)調(diào)試用的 ioctl 命令,以從驅(qū)動(dòng)程序拷貝相關(guān)的數(shù)命令,以從驅(qū)動(dòng)程序拷貝相關(guān)的數(shù)據(jù)到用戶(hù)空間據(jù)到用戶(hù)空間, 在這里你可以檢查它們。在這里你可以檢查它們。34第第4 章章 調(diào)試技術(shù)調(diào)試技術(shù)內(nèi)核中的調(diào)試支持內(nèi)核中的調(diào)試支持 通過(guò)打印調(diào)試通過(guò)打印調(diào)試 通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試 通過(guò)監(jiān)視調(diào)試通過(guò)監(jiān)視調(diào)試 調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障 調(diào)試器和相關(guān)工具調(diào)試器和相關(guān)工具35通過(guò)監(jiān)視調(diào)試通過(guò)監(jiān)視調(diào)試l通過(guò)監(jiān)視用戶(hù)空間中應(yīng)用程序的運(yùn)行情況,可以捕捉到一些通過(guò)監(jiān)視用戶(hù)空間中應(yīng)用程序的運(yùn)行情況,可以捕捉到一些問(wèn)題。有幾個(gè)方法可以用來(lái)監(jiān)視用戶(hù)空間程序運(yùn)行,問(wèn)題。有幾個(gè)方法可
38、以用來(lái)監(jiān)視用戶(hù)空間程序運(yùn)行, 你可以你可以運(yùn)行一個(gè)調(diào)試器來(lái)單步跟蹤它的函數(shù)運(yùn)行一個(gè)調(diào)試器來(lái)單步跟蹤它的函數(shù), 插入打印語(yǔ)句或者在插入打印語(yǔ)句或者在 strace 下運(yùn)行程序等等。本節(jié)主要討論下運(yùn)行程序等等。本節(jié)主要討論strace技術(shù)。技術(shù)。lstrace命令功能強(qiáng),可以顯示由用戶(hù)空間程序所發(fā)出的所有命令功能強(qiáng),可以顯示由用戶(hù)空間程序所發(fā)出的所有系統(tǒng)調(diào)用,包括調(diào)用參數(shù)及用符號(hào)表示的返回值系統(tǒng)調(diào)用,包括調(diào)用參數(shù)及用符號(hào)表示的返回值lstrace 有很多命令行選項(xiàng):有很多命令行選項(xiàng):-t :顯示每個(gè)調(diào)用發(fā)生的時(shí)間:顯示每個(gè)調(diào)用發(fā)生的時(shí)間-T:顯示調(diào)用所花費(fèi)的時(shí)間:顯示調(diào)用所花費(fèi)的時(shí)間 -e:限定被
39、跟蹤的調(diào)用類(lèi)型:限定被跟蹤的調(diào)用類(lèi)型-o:重定向輸出到一個(gè)文件中,:重定向輸出到一個(gè)文件中, 缺省情況下輸出到缺省情況下輸出到 stderr.lstrace 從內(nèi)核獲取信息,這意味著它可以跟蹤一個(gè)不帶有調(diào)從內(nèi)核獲取信息,這意味著它可以跟蹤一個(gè)不帶有調(diào)試支持試支持 (對(duì)對(duì) gcc是是 -g 選項(xiàng)選項(xiàng))以及去掉了符號(hào)信息的程序。以及去掉了符號(hào)信息的程序。36通過(guò)監(jiān)視調(diào)試通過(guò)監(jiān)視調(diào)試l例例 strace ls /dev /dev/scull0open(/dev, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY) = 3fstat64(3, st_mode=S_
40、IFDIR|0755, st_size=24576, .) = 0fcntl64(3, F_SETFD, FD_CLOEXEC) = 0getdents64(3, /* 141 entries */, 4096) = 4088.getdents64(3, /* 0 entries */, 4096) = 0close(3) = 0.fstat64(1, st_mode=S_IFCHR|0664, st_rdev=makedev(254, 0), .) = 0write(1, MAKEDEVnadmmidi0nadmmidi1nadmmid., 4096) = 4000write(1, bnpt
41、ywcnptywdnptywenptywfnptyx0n., 96) = 96write(1, bnptyxcnptyxdnptyxenptyxfnptyy0n., 4096) = 3904write(1, s17nvcs18nvcs19nvcs2nvcs20nvcs21., 192) = 192write(1, nvcs47nvcs48nvcs49nvcs5nvcs50nvc., 673) = 673close(1) = 0exit_group(0) = ?37通過(guò)監(jiān)視調(diào)試通過(guò)監(jiān)視調(diào)試l例例 用用wc命令讀命令讀scull設(shè)備設(shè)備.open(/dev/scull0, O_RDONLY|O_L
42、ARGEFILE) = 3fstat64(3, st_mode=S_IFCHR|0664, st_rdev=makedev(254, 0), .) = 0read(3, MAKEDEVnadmmidi0nadmmidi1nadmmid., 16384) = 4000read(3, bnptywcnptywdnptywenptywfnptyx0n., 16384) = 4000read(3, s17nvcs18nvcs19nvcs2nvcs20nvcs21., 16384) = 865read(3, , 16384) = 0fstat64(1, st_mode=S_IFCHR|0620, st_
43、rdev=makedev(136, 1), .) = 0write(1, 8865 /dev/scull0n, 17) = 17close(3) = 0exit_group(0) = ?38第第4 章章 調(diào)試技術(shù)調(diào)試技術(shù)內(nèi)核中的調(diào)試支持內(nèi)核中的調(diào)試支持 通過(guò)打印調(diào)試通過(guò)打印調(diào)試 通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試 通過(guò)監(jiān)視調(diào)試通過(guò)監(jiān)視調(diào)試 調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障 調(diào)試器和相關(guān)工具調(diào)試器和相關(guān)工具39調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障1. oops消息消息oops是內(nèi)核發(fā)生錯(cuò)誤時(shí)(比如引用了一個(gè)空指針)所是內(nèi)核發(fā)生錯(cuò)誤時(shí)(比如引用了一個(gè)空指針)所展現(xiàn)給我們的一系列信息,這些信息包含了當(dāng)時(shí)展現(xiàn)給我們的一系列信息,這
44、些信息包含了當(dāng)時(shí)CPU的狀態(tài)、進(jìn)程的狀態(tài)、內(nèi)核堆棧的狀態(tài)以及調(diào)用棧的的狀態(tài)、進(jìn)程的狀態(tài)、內(nèi)核堆棧的狀態(tài)以及調(diào)用棧的記錄等記錄等大部分系統(tǒng)故障都是引用大部分系統(tǒng)故障都是引用 NULL 指針或者使用其他不指針或者使用其他不正確指針值引起的,這類(lèi)故障通常會(huì)導(dǎo)致一個(gè)正確指針值引起的,這類(lèi)故障通常會(huì)導(dǎo)致一個(gè) oops 消息消息.40調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障l例例 faulty模塊中的模塊中的write調(diào)用由于引用空指針導(dǎo)致的調(diào)用由于引用空指針導(dǎo)致的oopsssize_t faulty_write (struct file *filp, const char _user *buf, size_t coun
45、t, loff_t *pos) *(int *)0 = 0; /*make a simple fault by dereferencing a NULL pointer */ return 0;41調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障Unable to handle kernel NULL pointer dereference at virtual address 00000000 printing eip:d083a064Oops: 0002 #1SMPCPU: 0EIP: 0060: Not taintedEFLAGS: 00010246 (2.6.6)EIP is at faulty_write+
46、0 x4/0 x10 faultyeax: 00000000 ebx: 00000000 ecx: 00000000 edx: 00000000esi: cf8b2460 edi: cf8b2480 ebp: 00000005 esp: c31c5f74ds: 007b es: 007b ss: 0068Process bash (pid: 2086, threadinfo=c31c4000 task=cfa0a6c0)Stack: c0150558 cf8b2460 080e9408 00000005 cf8b2480 00000000 cf8b2460 cf8b2460 fffffff7
47、080e9408 c31c4000 c0150682 cf8b2460 080e9408 00000005 cf8b2480 00000000 00000001 00000005 c0103f8f 00000001 080e9408 00000005 00000005Call Trace: vfs_write+0 xb8/0 x130 sys_write+0 x42/0 x70 syscall_call+0 x7/0 xbCode: 89 15 00 00 00 00 c3 90 8d 74 26 00 83 ec 0c b8 00 a6 83 d0說(shuō)明引發(fā)內(nèi)核錯(cuò)誤的原因說(shuō)明內(nèi)核錯(cuò)誤的事發(fā)現(xiàn)場(chǎng)
48、說(shuō)明錯(cuò)誤發(fā)生時(shí)函數(shù)調(diào)用鏈42調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障l例例 faulty模塊中的模塊中的read 調(diào)用由于緩沖區(qū)溢出引發(fā)的調(diào)用由于緩沖區(qū)溢出引發(fā)的oopsssize_t faulty_read(struct file *filp, char _user *buf, size_t count, loff_t *pos) int ret; char stack_buf4; /* Lets try a buffer overflow */ memset(stack_buf, 0 xff, 20); if (count 4) count = 4; /* copy 4 bytes to the user
49、 */ ret = copy_to_user(buf, stack_buf, count); if (!ret) return count; return ret;43調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障EIP: 0010:Unable to handle kernel paging request at virtual address ffffffff printing eip:ffffffffOops: 0000 #5SMPCPU: 0EIP: 0060: Not taintedEFLAGS: 00010296 (2.6.6)EIP is at 0 xffffffffeax: 0000000c ebx
50、: ffffffff ecx: 00000000 edx: bfffda7cesi: cf434f00 edi: ffffffff ebp: 00002000 esp: c27fff78ds: 007b es: 007b ss: 0068Process head (pid: 2331, threadinfo=c27fe000 task=c3226150)Stack: ffffffff bfffda70 00002000 cf434f20 00000001 00000286 cf434f00 fffffff7 bfffda70 c27fe000 c0150612 cf434f00 bfffda7
51、0 00002000 cf434f20 00000000 00000003 00002000 c0103f8f 00000003 bfffda70 00002000 00002000 bfffda70Call Trace: sys_read+0 x42/0 x70 syscall_call+0 x7/0 xbCode: Bad EIP value.44調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障2. 系統(tǒng)掛起系統(tǒng)掛起內(nèi)核代碼中的大多數(shù)錯(cuò)誤通常只會(huì)導(dǎo)致一個(gè)內(nèi)核代碼中的大多數(shù)錯(cuò)誤通常只會(huì)導(dǎo)致一個(gè)oops消息,但有時(shí)消息,但有時(shí)也會(huì)將系統(tǒng)掛起,系統(tǒng)真掛起時(shí)不會(huì)再響應(yīng)任何動(dòng)作,包括也會(huì)將系統(tǒng)掛起,系統(tǒng)真掛起時(shí)不會(huì)再響應(yīng)任
52、何動(dòng)作,包括Ctrl-Alt-Del 組合鍵組合鍵但有時(shí)系統(tǒng)不是真的掛起,只是某種原因使鍵盤(pán)被鎖住,此時(shí)可但有時(shí)系統(tǒng)不是真的掛起,只是某種原因使鍵盤(pán)被鎖住,此時(shí)可用用“SySRq魔法鍵(魔法鍵(magic SysRq key)”工具進(jìn)行調(diào)試工具進(jìn)行調(diào)試“ SySRq魔法鍵魔法鍵” 在大部分體系上都可用。在在大部分體系上都可用。在 PC 上,可通過(guò)上,可通過(guò)Alt 和和SysRq 鍵組合來(lái)激活,在別的平臺(tái)上可使用其他特殊鍵鍵組合來(lái)激活,在別的平臺(tái)上可使用其他特殊鍵(詳見(jiàn)詳見(jiàn) documentation/sysrq.txt)來(lái)激活來(lái)激活, 在串口控制臺(tái)上也可用在串口控制臺(tái)上也可用,由第三個(gè)鍵來(lái)決定
53、其動(dòng)作中,由第三個(gè)鍵來(lái)決定其動(dòng)作中: r :關(guān)閉鍵盤(pán)原始模式。用于當(dāng)某個(gè)崩潰的應(yīng)用程序:關(guān)閉鍵盤(pán)原始模式。用于當(dāng)某個(gè)崩潰的應(yīng)用程序( 例如例如 X 服務(wù)服務(wù)器器 )讓鍵盤(pán)處于一個(gè)奇怪狀態(tài)。讓鍵盤(pán)處于一個(gè)奇怪狀態(tài)。 k :調(diào)用:調(diào)用“安全注意鍵安全注意鍵”( SAK ) 功能功能. SAK 將殺掉在當(dāng)前控制臺(tái)將殺掉在當(dāng)前控制臺(tái)上的所有運(yùn)行的進(jìn)程上的所有運(yùn)行的進(jìn)程, 給你一個(gè)干凈的終端給你一個(gè)干凈的終端. S:對(duì)全部磁盤(pán)進(jìn)行緊急同步:對(duì)全部磁盤(pán)進(jìn)行緊急同步.45調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障 u:umount, 嘗試以只讀模式重新加載所有磁盤(pán)。嘗試以只讀模式重新加載所有磁盤(pán)。 這個(gè)操作常常在這個(gè)操作常常
54、在 s 之后馬上調(diào)用之后馬上調(diào)用, 它可以在系統(tǒng)處于嚴(yán)重故障時(shí)節(jié)省很多檢查文件它可以在系統(tǒng)處于嚴(yán)重故障時(shí)節(jié)省很多檢查文件系統(tǒng)的時(shí)間。系統(tǒng)的時(shí)間。 b:boot,立刻重啟系統(tǒng)。,立刻重啟系統(tǒng)。 確認(rèn)要先同步和重新加載磁盤(pán)。確認(rèn)要先同步和重新加載磁盤(pán)。 p :打印處理器寄存器消息。:打印處理器寄存器消息。 t: 打印當(dāng)前任務(wù)列表。打印當(dāng)前任務(wù)列表。 m :打印內(nèi)存信息。:打印內(nèi)存信息。魔法鍵魔法鍵SysRq 必須在內(nèi)核配置中顯式使能必須在內(nèi)核配置中顯式使能, 大部分的發(fā)布版沒(méi)有大部分的發(fā)布版沒(méi)有使能它使能它, 因?yàn)槊黠@的安全理由因?yàn)槊黠@的安全理由. 對(duì)于用來(lái)開(kāi)發(fā)驅(qū)動(dòng)的系統(tǒng)對(duì)于用來(lái)開(kāi)發(fā)驅(qū)動(dòng)的系統(tǒng),
55、使能魔使能魔法鍵法鍵SysRq是值得的。是值得的。魔法鍵魔法鍵 sysrq 能在運(yùn)行時(shí)關(guān)閉能在運(yùn)行時(shí)關(guān)閉, 使用如下命令使用如下命令:echo 0 /proc/sys/kernel/sysrq 46第第4 章章 調(diào)試技術(shù)調(diào)試技術(shù)內(nèi)核中的調(diào)試支持內(nèi)核中的調(diào)試支持 通過(guò)打印調(diào)試通過(guò)打印調(diào)試 通過(guò)查詢(xún)調(diào)試通過(guò)查詢(xún)調(diào)試 通過(guò)監(jiān)視調(diào)試通過(guò)監(jiān)視調(diào)試 調(diào)試系統(tǒng)故障調(diào)試系統(tǒng)故障 調(diào)試器和相關(guān)工具調(diào)試器和相關(guān)工具47調(diào)試器和相關(guān)工具調(diào)試器和相關(guān)工具lgdb調(diào)試內(nèi)核調(diào)試內(nèi)核gdb /usr/src/linux/vmlinux /proc/kcore Vmlinux:一參,指定待調(diào)試的文件為非壓縮內(nèi)核映像文件一參,
56、指定待調(diào)試的文件為非壓縮內(nèi)核映像文件 /proc/kcore:二參,指定內(nèi)核在內(nèi)存中的核心映像,對(duì)于一個(gè)運(yùn):二參,指定內(nèi)核在內(nèi)存中的核心映像,對(duì)于一個(gè)運(yùn)行的內(nèi)核,核心映像就是運(yùn)行時(shí)的內(nèi)核映像行的內(nèi)核,核心映像就是運(yùn)行時(shí)的內(nèi)核映像gdb可以打印結(jié)構(gòu)體中存放的信息、跟蹤一個(gè)指針、輸出一個(gè)變可以打印結(jié)構(gòu)體中存放的信息、跟蹤一個(gè)指針、輸出一個(gè)變量的值、反匯編一個(gè)函數(shù)等量的值、反匯編一個(gè)函數(shù)等 p jiffies disassemble function打印數(shù)據(jù)時(shí),內(nèi)核仍在運(yùn)行,各種數(shù)據(jù)在不同時(shí)間可能會(huì)有不同打印數(shù)據(jù)時(shí),內(nèi)核仍在運(yùn)行,各種數(shù)據(jù)在不同時(shí)間可能會(huì)有不同的值,但的值,但gdb將第一次讀取的數(shù)據(jù)
57、放在緩存中,第二次讀取時(shí)得將第一次讀取的數(shù)據(jù)放在緩存中,第二次讀取時(shí)得到的仍是原數(shù)據(jù)到的仍是原數(shù)據(jù)執(zhí)行命令執(zhí)行命令core-file /proc/kcore刷新緩沖區(qū)后再讀刷新緩沖區(qū)后再讀48調(diào)試器和相關(guān)工具調(diào)試器和相關(guān)工具lgdb調(diào)試可加載模塊調(diào)試可加載模塊上面的命令只可調(diào)試內(nèi)核,但對(duì)于可加載模塊卻上面的命令只可調(diào)試內(nèi)核,但對(duì)于可加載模塊卻無(wú)能為力,因?yàn)榭杉虞d模塊并沒(méi)有隨無(wú)能為力,因?yàn)榭杉虞d模塊并沒(méi)有隨vmlinux傳遞傳遞給給gdb,所以,所以gdb 對(duì)它一無(wú)所知對(duì)它一無(wú)所知 可加載模塊是可加載模塊是 ELF 格式的可執(zhí)行映象格式的可執(zhí)行映象, 它們被分它們被分成幾個(gè)代碼段成幾個(gè)代碼段.
58、一個(gè)典型的模塊可能包含一打或更一個(gè)典型的模塊可能包含一打或更多段多段, 以下以下 3 個(gè)段與調(diào)試相關(guān)個(gè)段與調(diào)試相關(guān): .text:這個(gè)段包含了模塊的可執(zhí)行代碼:這個(gè)段包含了模塊的可執(zhí)行代碼. .bss /.data :這:這 2 個(gè)段包含了模塊的變量個(gè)段包含了模塊的變量. 未初始化的未初始化的變量在變量在 .bss 中中, 已初始化的在已初始化的在 .data 里里.要想使要想使 gdb 能夠處理可加載模塊,必須告訴它模能夠處理可加載模塊,必須告訴它模塊的段加載位置。塊的段加載位置。49調(diào)試器和相關(guān)工具調(diào)試器和相關(guān)工具每個(gè)模塊在加載后都會(huì)在每個(gè)模塊在加載后都會(huì)在 /sys/module 目錄下
59、產(chǎn)生一目錄下產(chǎn)生一個(gè)對(duì)應(yīng)的目錄,在該目錄下又有一個(gè)個(gè)對(duì)應(yīng)的目錄,在該目錄下又有一個(gè)sections目錄,目錄,sections下有下有.text、.bss、.data三個(gè)文件,文件內(nèi)容三個(gè)文件,文件內(nèi)容就是就是3個(gè)段的基地址。個(gè)段的基地址。 例如例如, 在加載在加載 scull 模塊后模塊后, /sys/module/scull/sections 會(huì)包含一個(gè)名為會(huì)包含一個(gè)名為 .text 的的文件,文件的內(nèi)容就是代碼段的基地址文件,文件的內(nèi)容就是代碼段的基地址.通過(guò)通過(guò)sysfs文件獲取模塊的段地址后,就可以使用如下文件獲取模塊的段地址后,就可以使用如下命令進(jìn)行調(diào)試命令進(jìn)行調(diào)試(gdb) ad
60、d-symbol-file ./scull.ko 0 xd0832000 -s .bss 0 xd0837100 -s .data 0 xd0836be050調(diào)試器和相關(guān)工具調(diào)試器和相關(guān)工具例例 scull調(diào)試調(diào)試(gdb) add-symbol-file scull.ko 0 xd0832000 -s .bss 0 xd0837100 -s .data 0 xd0836be0add symbol table from file scull.ko at .text_addr = 0 xd0832000 .bss_addr = 0 xd0837100 .data_addr = 0 xd0836be0(y or n) yReading symbols from scu
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 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ì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 推廣部門(mén)業(yè)務(wù)管理制度
- 招生電話(huà)銷(xiāo)售管理制度
- 農(nóng)產(chǎn)品銷(xiāo)售管理制度
- 煤炭發(fā)運(yùn)站管理制度
- 制鞋工技能管理制度
- 網(wǎng)吧建設(shè)與管理制度
- 村級(jí)陣地日常管理制度
- 實(shí)驗(yàn)小學(xué)辦公室管理制度
- 道路養(yǎng)護(hù)站管理制度
- 先進(jìn)初中管理制度
- 2023年-2024年新《管理學(xué)原理》考試題庫(kù)(含答案)
- 深圳市企業(yè)數(shù)據(jù)合規(guī)指引
- 新能源汽車(chē)電機(jī)軸項(xiàng)目實(shí)施方案
- 2023年山東省青島市中考地理試卷(附詳細(xì)答案)
- 老年人能力評(píng)估標(biāo)準(zhǔn)解讀(講義)課件
- RTO工藝流程簡(jiǎn)介
- 電機(jī)行業(yè)報(bào)告
- 四年級(jí)下冊(cè)道德與法治知識(shí)點(diǎn)歸納
- 小學(xué)標(biāo)準(zhǔn)作文稿紙模板
- 工程計(jì)量及合同結(jié)算支付流程圖
- 糧食倉(cāng)儲(chǔ)(糧庫(kù))安全生產(chǎn)標(biāo)準(zhǔn)化管理體系全套資料匯編(2019-2020新標(biāo)準(zhǔn)實(shí)施模板)
評(píng)論
0/150
提交評(píng)論