溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Linux 后臺(tái)開發(fā)常用調(diào)試工具是什么

發(fā)布時(shí)間:2022-01-21 09:59:05 來源:億速云 閱讀:119 作者:kk 欄目:開發(fā)技術(shù)

本篇文章給大家分享的是有關(guān)Linux 后臺(tái)開發(fā)常用調(diào)試工具是什么,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

Linux入門

編譯階段

  • nm         獲取二進(jìn)制文件包含的符號(hào)信息
  • strings      獲取二進(jìn)制文件包含的字符串常量
  • strip        去除二進(jìn)制文件包含的符號(hào)
  • readelf      顯示目標(biāo)文件詳細(xì)信息
  • objdump     盡可能反匯編出源代碼
  • addr2line     根據(jù)地址查找代碼行

運(yùn)行階段

  • gdb         強(qiáng)大的調(diào)試工具
  • ldd         顯示程序需要使用的動(dòng)態(tài)庫和實(shí)際使用的動(dòng)態(tài)庫
  • strace       跟蹤程序當(dāng)前的系統(tǒng)調(diào)用
  • ltrace       跟蹤程序當(dāng)前的庫函數(shù)
  • time        查看程序執(zhí)行時(shí)間、用戶態(tài)時(shí)間、內(nèi)核態(tài)時(shí)間
  • gprof        顯示用戶態(tài)各函數(shù)執(zhí)行時(shí)間
  • valgrind      檢查內(nèi)存錯(cuò)誤
  • mtrace      檢查內(nèi)存錯(cuò)誤

其他

  • proc文件系統(tǒng)
  • 系統(tǒng)日志

02 編譯階段

nm(獲取二進(jìn)制文件里面包含的符號(hào))

符號(hào):函數(shù)、變量

參數(shù):

  • -C      把C++函數(shù)簽名轉(zhuǎn)為可讀形式
  • -A      列出符號(hào)名的時(shí)候同時(shí)顯示來自于哪個(gè)文件。
  • -a      列出所有符號(hào)(這將會(huì)把調(diào)試符號(hào)也列出來。默認(rèn)狀態(tài)下調(diào)試符號(hào)不會(huì)被列出)
  • -l       列出符號(hào)在源代碼中對(duì)應(yīng)的行號(hào)(指定這個(gè)參數(shù)后,nm將利用調(diào)試信息找出文件名以及符號(hào)的行號(hào)。對(duì)于一個(gè)已定義符號(hào),將會(huì)找出這個(gè)符號(hào)定義的行號(hào),對(duì)于未定義符號(hào),顯示為空)
  • -n      根據(jù)符號(hào)的地址來排序(默認(rèn)是按符號(hào)名稱的字母順序排序的)
  • -u      只列出未定義符號(hào)

strings(獲取二進(jìn)制文件里面的字符串常量)

功能:

獲取二進(jìn)制文件里面的字符串常量

用途:

比較重要的是檢查KEY泄露

eg:strings | grep '^.\{16\}$' 查找中是否存在一行有16個(gè)字符的行,并顯示出來。

選項(xiàng):

  • -a 不只是掃描目標(biāo)文件初始化和裝載段, 而是掃描整個(gè)文件。
  • -f 在顯示字符串之前先顯示文件名。
  • -n min-len打印至少min-len字符長的字符串.默認(rèn)的是4。
#strings /lib/tls/libc.so.6 | grep GLIBCGLIBC_2.0GLIBC_2.1GLIBC_2.1.1……

這樣就能看到glibc支持的版本。

strip(去除二進(jìn)制文件里面包含的符號(hào))

用途:

可執(zhí)行程序減肥(通常只在已經(jīng)調(diào)試和測試過的生成模塊上,因?yàn)椴荒苷{(diào)試了)

反編譯、反跟蹤

readelf(顯示目標(biāo)文件詳細(xì)信息)

nm 程序可用于列舉符號(hào)及其類型和值,但是,要更仔細(xì)地研究目標(biāo)文件中這些命名段的內(nèi)容,需要使用功能更強(qiáng)大的工具。其中兩種功能強(qiáng)大的工具是objdump和readelf。

readelf工具使用來顯示一個(gè)或多個(gè)ELF格式文件信息的GNU工具。使用不同的參數(shù)可以查看ELF文件不同的的信息。

readelf  
  • -a      顯示所有ELF文件的信息
  • -h      顯示ELF文件的文件頭
  • -l       顯示程序頭(program-header)和程序段(segment)和段下面的節(jié)
  • -S      顯示較為詳細(xì)的節(jié)信息(section)
  • -s      顯示符號(hào)信息,
  • -n      顯示標(biāo)識(shí)信息(如果有)
  • -r       顯示重定位信息(如果有)
  • -u      顯示展開函數(shù)信息(如果有)
  • -d      顯示動(dòng)態(tài)節(jié)信息,一般是動(dòng)態(tài)庫的信息

objdump(盡可能反匯編出源代碼)objdump –S

盡可能反匯編出源代碼,尤其當(dāng)編譯的時(shí)候指定了-g參數(shù)時(shí),效果比較明顯。

addr2line(根據(jù)地址查找代碼行)

當(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)的代碼行,很方便。

注意:

  1. 該可執(zhí)行程序用-g編譯,使之帶調(diào)試信息。
  2. 如果crash在一個(gè)so里面,那addr2line不能直接給出代碼行。

參數(shù):

  • -a   在顯示函數(shù)名或文件行號(hào)前顯示地址
  • -b   指定二進(jìn)制文件格式
  • -C   解析C++符號(hào)為用戶級(jí)的名稱,可指定解析樣式
  • -e   指定二進(jìn)制文件
  • -f    同時(shí)顯示函數(shù)名稱
  • -s   僅顯示文件的基本名,而不是完整路徑
  • -i    展開內(nèi)聯(lián)函數(shù)
  • -j    讀取相對(duì)于指定節(jié)的偏移而不是絕對(duì)地址
  • -p   每個(gè)位置都在一行顯示

03 運(yùn)行階段

調(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(顯示程序需要使用的動(dòng)態(tài)庫和實(shí)際使用的動(dòng)態(tài)庫)

# 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ì)沒有第二欄。

strace(跟蹤當(dāng)前系統(tǒng)調(diào)用)

結(jié)果默認(rèn)輸出到2。

  • -p “ attach到一個(gè)進(jìn)程
  • -c 最后統(tǒng)計(jì)各個(gè)system call的調(diào)用情況
  • -T 打印system call的調(diào)用時(shí)間
  • -t/-tt/-ttt 時(shí)間格式
  • -f/-F 跟蹤由fork/vfork調(diào)用所產(chǎn)生的子進(jìn)程
  • -o “,將strace的輸出定向到file中。

如:strace -f -o ~/

  • -e expr 指定一個(gè)表達(dá)式,用來控制如何跟蹤,格式如下:
  • -e open等價(jià)于-e trace=open,表示只跟蹤open調(diào)用

使用 strace –e open ./prg 來看程序使用了哪些配置文件或日志文件,很方便。

  • -e trace=“ 只跟蹤指定的系統(tǒng)調(diào)用

例如:-e trace=open,close,rean,write 表示只跟蹤這四個(gè)系統(tǒng)調(diào)用.

  • -e trace=file只跟蹤有關(guān)文件操作的系統(tǒng)調(diào)用
  • -e trace=process只跟蹤有關(guān)進(jìn)程控制的系統(tǒng)調(diào)用
  • -e trace=network跟蹤與網(wǎng)絡(luò)有關(guān)的所有系統(tǒng)調(diào)用
  • -e strace=signal 跟蹤所有與系統(tǒng)信號(hào)有關(guān)的系統(tǒng)調(diào)用
  • -e trace=ipc跟蹤所有與進(jìn)程通訊有關(guān)的系統(tǒng)調(diào)用

ltrace(跟蹤當(dāng)前庫函數(shù))

參數(shù)和strace很接近

time(查看程序執(zhí)行時(shí)間、用戶態(tài)時(shí)間、內(nèi)核態(tài)時(shí)間)

# 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(顯示用戶態(tài)各函數(shù)執(zhí)行時(shí)間)

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ù)列表:

  • %p – insert pid into filename 添加pid
  • %u – insert current uid into filename 添加當(dāng)前uid
  • %g – insert current gid into filename 添加當(dāng)前gid
  • %s – insert signal that caused the coredump into the filename 添加導(dǎo)致產(chǎn)生core的信號(hào)
  • %t – insert UNIX time that the coredump occurred into filename 添加core文件生成時(shí)的unix時(shí)間
  • %h – insert hostname where the coredump happened into filename 添加主機(jī)名
  • %e – insert coredumping executable name into filename 添加命令名

使用gdb查看core:

gdb  

opprofile (查看CPU耗在哪)

常用命令

使用oprofile進(jìn)行cpu使用情況檢測,需要經(jīng)過初始化、啟動(dòng)檢測、導(dǎo)出檢測數(shù)據(jù)、查看檢測結(jié)果等步驟,以下為常用的oprofile命令。

初始化

  • opcontrol –no-vmlinux : 指示oprofile啟動(dòng)檢測后,不記錄內(nèi)核模塊、內(nèi)核代碼相關(guān)統(tǒng)計(jì)數(shù)據(jù)
  • opcontrol –init : 加載oprofile模塊、oprofile驅(qū)動(dòng)程序

檢測控制

  • opcontrol –start : 指示oprofile啟動(dòng)檢測
  • opcontrol –dump : 指示將oprofile檢測到的數(shù)據(jù)寫入文件
  • opcontrol –reset : 清空之前檢測的數(shù)據(jù)記錄
  • opcontrol -h : 關(guān)閉oprofile進(jìn)程

查看檢測結(jié)果

  • opreport : 以鏡像(image)的角度顯示檢測結(jié)果,進(jìn)程、動(dòng)態(tài)庫、內(nèi)核模塊屬于鏡像范疇
  • opreport -l : 以函數(shù)的角度顯示檢測結(jié)果
  • opreport -l test : 以函數(shù)的角度,針對(duì)test進(jìn)程顯示檢測結(jié)果
  • opannotate -s test : 以代碼的角度,針對(duì)test進(jìn)程顯示檢測結(jié)果
  • opannotate -s /lib64/libc-2.4.so : 以代碼的角度,針對(duì)libc-2.4.so庫顯示檢測結(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

valgrind(檢查內(nèi)存錯(cuò)誤)

使用步驟:

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(檢查內(nèi)存錯(cuò)誤)

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()。

04 其他

proc文件系統(tǒng)

內(nèi)核的窗口。

proc文件系統(tǒng)是一個(gè)偽文件系統(tǒng),它存在內(nèi)存當(dāng)中,而不占用外存空間。

用戶和應(yīng)用程序可以通過proc得到系統(tǒng)的信息,并可以改變內(nèi)核的某些參數(shù)。

proc/目錄結(jié)構(gòu)(部分):

  • cmdline         內(nèi)核命令行
  • cpuinfo          關(guān)于Cpu信息
  • devices         可以用到的設(shè)備(塊設(shè)備/字符設(shè)備)
  • filesystems      支持的文件系統(tǒng)
  • interrupts        中斷的使用
  • ioports          I/O端口的使用
  • kcore           內(nèi)核核心映像
  • kmsg           內(nèi)核消息
  • meminfo     內(nèi)存信息
  • mounts         加載的文件系統(tǒng)
  • stat            全面統(tǒng)計(jì)狀態(tài)表
  • swaps          對(duì)換空間的利用情況
  • version          內(nèi)核版本
  • uptime          系統(tǒng)正常運(yùn)行時(shí)間
  • net             網(wǎng)絡(luò)信息
  • sys            可寫,可以通過它來訪問或修改內(nèi)核的參數(shù)

proc//目錄結(jié)構(gòu)(部分):

  • cmdline         命令行參數(shù)
  • environ          環(huán)境變量值
  • fd             一個(gè)包含所有文件描述符的目錄
  • mem           進(jìn)程的內(nèi)存被利用情況
  • stat            進(jìn)程狀態(tài)
  • status          Process status in human readable form
  • cwd            當(dāng)前工作目錄的鏈接
  • exe            Link to the executable of this process
  • maps           內(nèi)存映像
  • statm           進(jìn)程內(nèi)存狀態(tài)信息
  • root            鏈接此進(jìn)程的root目錄

系統(tǒng)日志

/var/log/下的日志文件:

  • /var/log/messages     整體系統(tǒng)信息,其中也包含系統(tǒng)啟動(dòng)期間的日志。此外,mail、cron、daemon、kern和auth等內(nèi)容也記錄在var/log/messages日志中。
  • /var/log/auth.log       系統(tǒng)授權(quán)信息,包括用戶登錄和使用的權(quán)限機(jī)制等。
  • /var/log/boot.log       系統(tǒng)啟動(dòng)時(shí)的日志。
  • /var/log/daemon.log    各種系統(tǒng)后臺(tái)守護(hù)進(jìn)程日志信息。
  • /var/log/lastlog           記錄所有用戶的最近信息。這不是一個(gè)ASCII文件,因此需要用lastlog命令查看內(nèi)容。
  • /var/log/user.log       記錄所有等級(jí)用戶信息的日志。
  • /var/log/cron         每當(dāng)cron進(jìn)程開始一個(gè)工作時(shí),就會(huì)將相關(guān)信息記錄在這個(gè)文件中。
  • /var/log/wtmp或utmp   登錄信息。
  • /var/log/faillog        用戶登錄失敗信息。此外,錯(cuò)誤登錄命令也會(huì)記錄在本文件中。

什么是Linux系統(tǒng)

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è)資訊頻道。

向AI問一下細(xì)節(jié)

免責(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)容。

AI