第10章 嵌入式linux的调试技术
一、????? 防止函數(shù)printk降低linux性能:
利用C語言中的編譯指令(#if、#else、#endif等)。
現(xiàn)在修改printk_demo驅(qū)動代碼,通過編譯指令定義了一個pr_debug宏,并通過修改編譯指令的條件值來控制是否調(diào)用printk函數(shù)。如下:
# if 1//此處為1,使用printk函數(shù),為0,忽略printk函數(shù)
? #define pr_debug(x,…)? do { } while(0)
#endif
除此之外,我們還需要了解兩個知識點:1.可變參數(shù)的宏:可變參數(shù)的宏與固定參數(shù)的宏之間的區(qū)別:可變參數(shù)的宏需要通過_VA_ARGS_宏【不支持可變參數(shù)個數(shù)為0的情況】獲取可變參數(shù)的宏的可變參數(shù)。定義可變參數(shù)宏與定義可變參數(shù)函數(shù)的方法相同,都使用3個點(…)來表示可變參數(shù),可變參數(shù)必須是宏和函數(shù)最后的參數(shù)。
二、????? 通過虛擬文件系統(tǒng)(/proc)進(jìn)行數(shù)據(jù)交互:
必要性:在linux文件系統(tǒng)中,/proc經(jīng)常被用來作為內(nèi)核空間進(jìn)行數(shù)據(jù)交互的工具。/proc是虛擬文件系統(tǒng),也就是說,/proc并不是真正的文件系統(tǒng),而是內(nèi)存映射。所有讀寫/proc的操作軍事對內(nèi)存讀寫的操作。所以讀寫/proc文件系統(tǒng)的速度遠(yuǎn)比讀寫/dev要快。因此,/proc文件系統(tǒng)也可作為linux驅(qū)動與用戶空間程序交互的工具。
很多信息就是通過/proc文件系統(tǒng)由內(nèi)核空間的程序向外屆提供的。例如:當(dāng)前系統(tǒng)內(nèi)存資源就是通過/proc/meminfo文件讀取的,讀者可以使用如下命令:查看/proc/meminfo文件的內(nèi)容:Cat /proc/meminfo.我們可以通過執(zhí)行free命令看看顯示的信息是否和meminfo文件中的部分內(nèi)容相匹配。
在linux驅(qū)動程序中可以使用內(nèi)核函數(shù)在/proc目錄中創(chuàng)建和刪除虛擬文件,也可以建立和刪除虛擬目錄。
struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,struct proc_dir_entry *parent);
name:?要創(chuàng)建的文件名稱;
mode:?該文件的保護(hù)掩碼;
parent:?確定文件所在目錄,如果置NULL?,則位置為/proc?下。
/*?該函數(shù)在父目錄parent?下創(chuàng)建一個目錄name* */
struct proc_dir_entry * proc_mkdir (const char *name,struct proc_dir_entry *parent);
@name :?要創(chuàng)建的目錄名
@parent :?這個目錄的父目錄
3.remove_proc_entry 刪除文件或目錄
/*?這個函數(shù)從proc?文件系統(tǒng)中刪除一個文件或目錄。
*?注意:1?.是通過參數(shù)name?,而不是通過創(chuàng)建時返回的指針來刪除的。
* 2?.該函數(shù)不會遞歸刪除目錄下的文件。
* 3?.data?變量保存了分配的內(nèi)存,要先釋放對應(yīng)內(nèi)存,再刪除該文件。
* */
void remove_proc_entry (const char *name,struct proc_dir_entry *parent);
@name :?要刪除的文件或目錄名
@parent :?所在的父目錄?
?4.create_proc_read_entry?創(chuàng)建只讀proc?文件
struct proc_dir_entry * create_proc_read_entry (const char
*name,mode_t mode,struct proc_dir_entry *parent,read_proc_t*
read_proc,void *data);
@name :?要創(chuàng)建的文件名
@mode :?要創(chuàng)建的文件的屬性 默認(rèn)0755
@parent :?這個文件的父目錄
@read_proc :?當(dāng)用戶讀這個文件時,內(nèi)核調(diào)用的函數(shù)
@data :?傳給read_proc?的參數(shù)
注意:刪除虛擬文件目錄之前,要先刪除目錄中的虛擬文件。
執(zhí)行build.sh腳本文件,會將proc_demo驅(qū)動安裝在Ubuntu Linux、開發(fā)板或Android虛擬機(jī)上。然后執(zhí)行下面的命令查看/proc/proc_demo目錄中的內(nèi)容。
Ls –al /proc/proc_demo/bin2dec
Cat /proc/proc_demo/bin2dec
Cat /proc_demo/readonly
三、????? 調(diào)試工具:
Gdb可以跟蹤調(diào)試用戶空間的程序。
對于一個用于測試的可執(zhí)行程序(gdb_debug.c),我們可以直接運行build.sh腳本文件,但注意加上命令參數(shù)-g,完整的編譯命令如下:
#gcc –static –g –o gdb_debug /root/drivers/debug/gdb_debug.c
現(xiàn)在使用下面的命令來調(diào)試:
Gdb gdb_debug
Gdb包含的命令:
1>???????? quit:用于退出gdb調(diào)試界面
2>???????? ?list:用于列出程序中的代碼。有三種調(diào)用格式:list:顯示上一次調(diào)用list命令輸出的最后一行后面的10行。 list-: 顯示上一次調(diào)用list命令輸出的第一行前面的10行,第一次調(diào)用list命令什么都不會顯示。list n:顯示第n行附近的10行,一般會顯示第n行前面5 行和后面4行,加上第n行,正好是10行。
3>???????? Break n:將指定行設(shè)置為斷點,n表示行號
4>???????? Clear n:清除指定行的斷點。
5>???????? Tbreak n:將指定行設(shè)置為斷點,斷點只能使用一次,使用完成后自動清零。
6>???????? Cont/continue:跳過當(dāng)前斷點繼續(xù)執(zhí)行。[cont:跳過當(dāng)前斷點繼續(xù)執(zhí)行;cont n:跳過n次斷點繼續(xù)前行]
7>???????? Next:繼續(xù)執(zhí)行下面的語句,但跳過這程序。等價于step over。[同上有兩種格式next 及next n]
8>???????? Nexti:單步執(zhí)行語句,和next的區(qū)別:它會跟蹤到子程序的內(nèi)部,但不打印出子程序內(nèi)部的語句。
9>???????? Print var_name:查看變量值.
1.與GDB的區(qū)別:gdb用于PC上進(jìn)行測試,而gdbserver測試運行于開發(fā)板、手機(jī)、Android模擬器上。
2.在開發(fā)板上使用gdbserver打開測試程序,然后通過串口、有線、無線網(wǎng)絡(luò)可以在PC上進(jìn)行測試。
3.第一步:進(jìn)入Android模擬器的終端,然后進(jìn)入data/local目錄,并執(zhí)行如下命令:gdbserver :4321 ./gdb_debug啟動gdbserver監(jiān)聽程序。其中4321表示使用本機(jī)的4321端口號進(jìn)行監(jiān)聽。
? 第二步:開啟另一個Linux終端,將外部訪問模擬器的4321端口的數(shù)據(jù)包轉(zhuǎn)發(fā)到Android模擬器內(nèi)部的4321端口:adb –s emulator-5544 forword tcp:4321[有多個Android設(shè)備時要加-s命令行參數(shù)指定具體的Android設(shè)備]。
第二個方法[映射端口]:1.進(jìn)入telent:telent localhost 5554 2.映射端口:redir add tcp:4321:4321
第三步:進(jìn)入gdb控制臺:arm-none-linux-guneabi-gdb gdb_debug
第四步:連接Android模擬器:(gdb) target remote localhost:4321
??????????? 最后:輸入gdb命令進(jìn)行調(diào)試。
??????? 通過IP方式連接開發(fā)板上的gdbserver:1.gdbserver localhost:4321 ./gdb_debug? 2.在linux終端的gdb控制臺鏈接開發(fā)板的gdbsrever:(gdb) target remote 192.168.17.103 ./gdb_debug.
??????? 通過串口方式:對應(yīng)的應(yīng)該是:1.gdbserver /dev/s3c2410_serial0 ./gdb_debug? 2.(gdb) target remote /dev/ttyUSB0
Kgdb除了提供類似printk函數(shù)的日志輸出功能,還允許開發(fā)人員直接在PC上通過GDB鏈接目標(biāo)設(shè)備。
Kgdb包含兩個部分:kgdb內(nèi)核和一套鏈接接口【目前支持串口tty設(shè)備鏈接和以太網(wǎng)連接】。其中串口連接需要通過內(nèi)核參數(shù)kgdboc指定要鏈接的串口tty設(shè)備:以太網(wǎng)連接通過內(nèi)核參數(shù)kgdboc指定IP和端口號。
要想用kgdb調(diào)試內(nèi)核,首先需要配置linux內(nèi)核。使用make menuconfig命令進(jìn)入Linux內(nèi)核的配置菜單。【Kernel hacking--àKGDB:kernel debugger】
???? 配置內(nèi)核參數(shù)時,這些參數(shù)通知Linux內(nèi)核要如何進(jìn)行調(diào)試。假設(shè)要通過USB轉(zhuǎn)COM口數(shù)據(jù)線進(jìn)行調(diào)試,需要將kgdboc參數(shù)值折為ttyUSB0,傳輸效率為115200,一般會指定kdbwait。這些參數(shù)需要在S3C開發(fā)板過程中按回車進(jìn)入Uboot模式,然后使用setenv命令設(shè)置Linux內(nèi)核的啟動參數(shù),然后使用saveenv和rest命令保存和重新啟動Linux內(nèi)核。
在設(shè)置完成后,主機(jī)就可以使用gdb命令像調(diào)試普通嵌入式應(yīng)用程序一樣調(diào)試Linux內(nèi)核,執(zhí)行的命令如下:
#gdb? ./vmlinux
完成后,使用如下的命令設(shè)置傳輸速率和連接也要調(diào)試的Linux內(nèi)核。
(gdb) set remoteband 115200
(gdb) target remote /dev/ttyUSB0
最后使用各種gdb命令進(jìn)行Linux內(nèi)核調(diào)試。
?
轉(zhuǎn)載于:https://www.cnblogs.com/beatrice/p/5656055.html
總結(jié)
以上是生活随笔為你收集整理的第10章 嵌入式linux的调试技术的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 闲暇处才是生活
- 下一篇: C#正则表达式提取文本中以逗号间隔的数据