您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關(guān)Linux 后臺(tái)開發(fā)常用調(diào)試工具是什么,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
符號(hào):函數(shù)、變量
參數(shù):
功能:
獲取二進(jìn)制文件里面的字符串常量
用途:
比較重要的是檢查KEY泄露
eg:strings | grep '^.\{16\}$'
查找
選項(xiàng):
#strings /lib/tls/libc.so.6 | grep GLIBCGLIBC_2.0GLIBC_2.1GLIBC_2.1.1……
這樣就能看到glibc支持的版本。
用途:
可執(zhí)行程序減肥(通常只在已經(jīng)調(diào)試和測試過的生成模塊上,因?yàn)椴荒苷{(diào)試了)
反編譯、反跟蹤
nm 程序可用于列舉符號(hào)及其類型和值,但是,要更仔細(xì)地研究目標(biāo)文件中這些命名段的內(nèi)容,需要使用功能更強(qiáng)大的工具。其中兩種功能強(qiáng)大的工具是objdump和readelf。
readelf工具使用來顯示一個(gè)或多個(gè)ELF格式文件信息的GNU工具。使用不同的參數(shù)可以查看ELF文件不同的的信息。
readelf
objdump(盡可能反匯編出源代碼)objdump –S
盡可能反匯編出源代碼,尤其當(dāng)編譯的時(shí)候指定了-g參數(shù)時(shí),效果比較明顯。
當(dāng)某個(gè)進(jìn)程崩潰時(shí),日志文件(/var/log/messages)中就會(huì)給出附加的信息,包括程序終止原因、故障地址,以及包含程序狀態(tài)字(PSW)、通用寄存器和訪問寄存器的簡要寄存器轉(zhuǎn)儲(chǔ)。
eg:Mar 31 11:34:28 l02 kernel: failing address: 0
如果可執(zhí)行文件包括調(diào)試符號(hào)(帶-g編譯的),使用addr2line,可以確定哪一行代碼導(dǎo)致了問題。
eg:addr2line –e exe addr
其實(shí)gdb也有這個(gè)功能,不過addr2line的好處是,很多時(shí)候,bug很難重現(xiàn),我們手上只有一份crash log。這樣就可以利用addr2line找到對(duì)應(yīng)的代碼行,很方便。
注意:
參數(shù):
調(diào)試程序的常見步驟:
1、確定運(yùn)行時(shí)間主要花在用戶態(tài)還是內(nèi)核態(tài)(比較土的一個(gè)方法:程序暫時(shí)屏蔽daemon()調(diào)用,hardcode收到n個(gè)請(qǐng)求后exit(0),time一下程序……)。
2、如果是用戶態(tài),則使用gprof進(jìn)行性能分析。
3、如果是內(nèi)核態(tài),則使用strace進(jìn)行性能分析,另外可以使用其他工具(比如ltrace等)輔助。
# ldd /bin/lslinux-gate.so.1 => (0xbfffe000)librt.so.1 => /lib/librt.so.1 (0xb7f0a000)libacl.so.1 => /lib/libacl.so.1 (0xb7f04000)libc.so.6 => /lib/libc.so.6 (0xb7dc3000)libpthread.so.0 => /lib/libpthread.so.0 (0xb7dab000)/lib/ld-linux.so.2 (0xb7f1d000)libattr.so.1 => /lib/libattr.so.1 (0xb7da6000)
第一欄:需要用什么庫;第二欄:實(shí)際用哪個(gè)庫文件;第三欄:庫文件裝載地址。
如果缺少動(dòng)態(tài)庫,就會(huì)沒有第二欄。
結(jié)果默認(rèn)輸出到2。
如:strace -f -o ~/
使用 strace –e open ./prg
來看程序使用了哪些配置文件或日志文件,很方便。
例如:-e trace=open,close,rean,write
表示只跟蹤這四個(gè)系統(tǒng)調(diào)用.
參數(shù)和strace很接近
# time ps aux | grep 'hi'1020 21804 0.0 0.0 1888 664 pts/6 S+ 17:46 0:00 grep hireal 0m0.009suser 0m0.000ssys 0m0.004s
注意:
time只跟蹤父進(jìn)程,所以不能fork
gprof原理:
在編譯和鏈接程序的時(shí)候(使用 -pg 編譯和鏈接選項(xiàng)),gcc在你應(yīng)用程序的每個(gè)函數(shù)中都加入了一個(gè)名為mcount(or“_mcount”, or“__mcount”)的函數(shù),也就是說-pg編譯的應(yīng)用程序里的每一個(gè)函數(shù)都會(huì)調(diào)用mcount, 而mcount會(huì)在內(nèi)存中保存一張函數(shù)調(diào)用圖,并通過函數(shù)調(diào)用堆棧的形式查找子函數(shù)和父函數(shù)的地址。這張調(diào)用圖也保存了所有與函數(shù)相關(guān)的調(diào)用時(shí)間,調(diào)用次數(shù)等等的所有信息。
使用步驟:
1、使用 -pg 編譯和鏈接應(yīng)用程序
gcc -pg -o exec exec.c
如果需要庫函數(shù)調(diào)用情況:
gcc -lc_p -gp -o exec exec.c
2、執(zhí)行應(yīng)用程序使之生成供gprof 分析的數(shù)據(jù)gmon.out
3、使用gprof 程序分析應(yīng)用程序生成的數(shù)據(jù)
gprof exec gmon.out > profile.txt
注意:
程序必須通過正常途徑退出(exit()、main返回),kill無效。對(duì)后臺(tái)常駐程序的調(diào)試——我的比較土方法是,屏蔽daemon()調(diào)用,程序hardcode收到n個(gè)請(qǐng)求后exit(0)。
有時(shí)不太準(zhǔn)。
只管了用戶態(tài)時(shí)間消耗,沒有管內(nèi)核態(tài)消耗。
gdb core exec
(gdb查看core文件) 準(zhǔn)備生成core:
啟動(dòng)程序前,ulimit -c unlimited
,設(shè)置core文件不限制大小。(相反,ulimit -c 0
,可以阻止生成core文件)
默認(rèn)在可執(zhí)行程序的路徑,生成的是名字為core的文件,新的core會(huì)覆蓋舊的。
設(shè)置core文件名字:
/proc/sys/kernel/core_uses_pid
可以控制產(chǎn)生的core文件的文件名中是否添加pid作為擴(kuò)展,1為擴(kuò)展,否則為0。
proc/sys/kernel/core_pattern
可以設(shè)置格式化的core文件保存位置或文件名,比如原來文件內(nèi)容是core,可以修改為:
echo "/data/core/core-%e-%p-%t" > core_pattern
以下是參數(shù)列表:
使用gdb查看core:
gdb
常用命令
使用oprofile進(jìn)行cpu使用情況檢測,需要經(jīng)過初始化、啟動(dòng)檢測、導(dǎo)出檢測數(shù)據(jù)、查看檢測結(jié)果等步驟,以下為常用的oprofile命令。
初始化
檢測控制
查看檢測結(jié)果
linux # opreportCPU: Core 2, speed 2128.07 MHz (estimated) Counted CPU_CLK_UNHALTED events (Clock cycles when not halted) with a unit mask of 0x00 (Unhalted core cycles) count 100000CPU_CLK_UNHALT.........| samples | %| ------------------------ 31645719 87.6453 no-vmlinux 4361113 10.3592 libend.so 7683 0.1367 libpython2.4.so.1.0 7046 0.1253 op_test
使用步驟:
1、官網(wǎng)下載并安裝valgrind。
2、-g編譯的程序都可以使用。
官網(wǎng)的示例代碼test.c
#include void f(void){ int* x = malloc(10 * sizeof(int)); x[10] = 0; // problem 1: heap block overrun} // problem 2: memory leak -- x not freedint main(void){ f(); return 0;}
編譯程序gcc -Wall -g -o test test.c
3、valgrind啟動(dòng)程序,屏幕輸出結(jié)果。
valgrind --tool=memcheck --leak-check=full ./test
注意:
valgrind只能查找堆內(nèi)存的訪問錯(cuò)誤,對(duì)棧上的對(duì)象和靜態(tài)對(duì)象沒辦法。
valgrind會(huì)影響進(jìn)程性能,據(jù)說可能慢20倍,所以在性能要求高的情況下,只能使用mtrace這種輕量級(jí)的工具了(但是mtrace只能識(shí)別簡單的內(nèi)存錯(cuò)誤)。
如果程序生成的core的堆棧是錯(cuò)亂的,那么基本上是stackoverflow了。這種情況,可以通過在編譯的時(shí)候,加上 –fstack-protector-all
和 -D_FORTIFY_SOURCE=2
來檢測。Stack-protector-all
會(huì)在每個(gè)函數(shù)里加上堆棧保護(hù)的代碼,并在堆棧上留上指紋。(記錄下,沒用過)
因?yàn)関algrind 查不了棧和靜態(tài)對(duì)象的內(nèi)存訪問越界,這類問題,可以通過使用gcc的-fmudflap –lmudflap
來檢測。(記錄下,沒用過)
全局變量的類型不一致的問題,現(xiàn)在還找到比較好的方法,這從另一個(gè)方面說明全局對(duì)象不是個(gè)好的設(shè)計(jì),這給調(diào)試帶來了麻煩。
mtrace是glibc內(nèi)提供的工具,原理很簡單,就是把你程序中malloc()和free()的位置全部下來,最后兩輛配對(duì),沒有配對(duì)到的就是memory leak。
使用的步驟如下:
1、代碼中添加mtrace()
#include #include int main(void){ int *p; int i;#ifdef DEBUG setenv("MALLOC_TRACE", "./memleak.log", 1); mtrace();#endif p=(int *)malloc(1000); return 0;}
這段代碼malloc了一個(gè)空間,卻沒有free掉。我們添加9-12行的mtrace調(diào)用。
2、編譯gcc -g -DDEBUG -o test1 test1.c
3、執(zhí)行./test1
,在目錄里會(huì)發(fā)現(xiàn)./memleak.log
。
4、使用mtrace memleak.log
查看信息。
# mtrace test1 memleak.log- 0x0804a008 Free 3 was never alloc'd 0xb7e31cbe- 0x0804a100 Free 4 was never alloc'd 0xb7ec3e3f- 0x0804a120 Free 5 was never alloc'd 0xb7ec3e47Memory not freed:-----------------Address Size Caller0x0804a4a8 0x3e8 at /home/illidanliu/test1.c:14
可以看到test1.c沒有對(duì)應(yīng)的free()。
內(nèi)核的窗口。
proc文件系統(tǒng)是一個(gè)偽文件系統(tǒng),它存在內(nèi)存當(dāng)中,而不占用外存空間。
用戶和應(yīng)用程序可以通過proc得到系統(tǒng)的信息,并可以改變內(nèi)核的某些參數(shù)。
proc/目錄結(jié)構(gòu)(部分):
proc//
目錄結(jié)構(gòu)(部分):
/var/log/
下的日志文件:
Linux是一種免費(fèi)使用和自由傳播的類UNIX操作系統(tǒng),是一個(gè)基于POSIX的多用戶、多任務(wù)、支持多線程和多CPU的操作系統(tǒng),使用Linux能運(yùn)行主要的Unix工具軟件、應(yīng)用程序和網(wǎng)絡(luò)協(xié)議。
以上就是Linux 后臺(tái)開發(fā)常用調(diào)試工具是什么,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。