編譯自:http://linoxide.com/linux-how-to/user-space-debugging-tools-linux/作者: B N Poornima 原創(chuàng):LCTThttps://linux.cn/article-5047-1.html譯者: mtunique 本文地址:https://linux.cn/article-5047-1.html
根據(jù)定義,調(diào)試工具是那些那些使我們能夠監(jiān)測、控制和糾正其他程序的程序。我們?yōu)槭裁磻?yīng)該用調(diào)試工具呢? 在有些情況下,運行一些程序的時候我們會被卡住,我們需要明白究竟發(fā)生了什么。 例如,我們正在運行應(yīng)用程序,它產(chǎn)生了一些錯誤消息。要修復(fù)這些錯誤,我們應(yīng)該先找出為什么產(chǎn)生這些錯誤的消息和這些錯誤消息從哪里產(chǎn)生的。 一個應(yīng)用程序可能突然掛起,我們必須了解其他什么進程同時在運行。我們可能還必須弄清楚某個進程掛起的時候在做什么。為了剖析這些細節(jié), 我們需要調(diào)試工具的幫助。
(題圖來自:axxomovies.org)
有幾個Linux下的用戶空間調(diào)試工具和技術(shù),它們用來分析用戶空間的問題相當有用。它們是:
'查詢 (/proc, /sys 等)跟蹤 (strace/ltrace)Valgrind (memwatch)GDB讓我們一個個地了解。
這是一個基本的原始的調(diào)試問題的方法。 我們可以在程序中插入print語句來了解控制流和變量值。 雖然這是一個簡單的技術(shù), 但它有一些缺點。 程序需要進行編輯以添加'print'語句,然后必須重新編譯,重新運行來獲得輸出。 如果要調(diào)試的程序相當大,這是一個耗時的方法。
在某些情況下,我們需要弄清楚在一個運行在內(nèi)核中的進程的狀態(tài)和內(nèi)存映射。為了獲得這些信息,我們不需要在內(nèi)核中插入任何代碼。 相反,可以用 /proc 文件系統(tǒng)。
/proc 是一個偽文件系統(tǒng),系統(tǒng)一啟動運行就收集著運行時系統(tǒng)的信息 (cpu信息, 內(nèi)存容量等)。
'ls /proc'的輸出
正如你看到的, 系統(tǒng)中運行的每一個進程在/proc文件系統(tǒng)中有一個以進程id命名的項。每個進程的細節(jié)信息可以在進程id對應(yīng)的目錄下的文件中獲得。
'ls /proc/pid'的輸出
解釋/proc文件系統(tǒng)內(nèi)的所有條目超出了本文的范圍。一些有用的列舉如下:
/proc/cmdline -> 內(nèi)核命令行/proc/cpuinfo -> 關(guān)于處理器的品牌,型號信息等/proc/filesystems -> 文件系統(tǒng)的內(nèi)核支持的信息/proc/<pid>/cmdline -> 命令行參數(shù)傳遞到當前進程/proc/<pid>/mem -> 當前進程持有的內(nèi)存/proc/<pid>/status -> 當前進程的狀態(tài)strace的和ltrace是兩個在Linux中用來追蹤程序的執(zhí)行細節(jié)的跟蹤工具。
strace攔截和記錄系統(tǒng)調(diào)用及其接收的信號。對于用戶,它顯示了系統(tǒng)調(diào)用、傳遞給它們的參數(shù)和返回值。strace的可以附著到已在運行的進程或一個新的進程。它作為一個針對開發(fā)者和系統(tǒng)管理員的診斷、調(diào)試工具是很有用的。它也可以用來當做一個通過跟蹤不同的程序調(diào)用來了解系統(tǒng)的工具。這個工具的好處是不需要源代碼,程序也不需要重新編譯。
使用strace的基本語法是:
strace 命令
strace有各種各樣的參數(shù)。可以檢查看strace的手冊頁來獲得更多的細節(jié)。
strace的輸出非常長,我們通常不會對顯示的每一行都感興趣。我們可以用'-e expr'選項來過濾不想要的數(shù)據(jù)。
用 '-p pid' 選項來綁到運行中的進程.
用'-o'選項,命令的輸出可以被重定向到文件。
strace過濾成只有系統(tǒng)調(diào)用的輸出
ltrace跟蹤和記錄一個進程的動態(tài)(運行時)庫的調(diào)用及其收到的信號。它也可以跟蹤一個進程所作的系統(tǒng)調(diào)用。它的用法是類似與strace。
ltrace command
'-i' 選項在調(diào)用庫時打印指令指針。
'-S' 選項被用來現(xiàn)實系統(tǒng)調(diào)用和庫調(diào)用
所有可用的選項請參閱ltrace手冊。
ltrace捕捉'STRCMP'庫調(diào)用的輸出
Valgrind是一套調(diào)試和分析工具。它的一個被廣泛使用的默認工具——'Memcheck'——可以攔截malloc(),new(),free()和delete()調(diào)用。換句話說,它在檢測下面這些問題非常有用:
內(nèi)存泄露重釋放訪問越界使用未初始化的內(nèi)存使用已經(jīng)被釋放的內(nèi)存等。它直接通過可執(zhí)行文件運行。
Valgrind也有一些缺點,因為它增加了內(nèi)存占用,會減慢你的程序。它有時會造成誤報和漏報。它不能檢測出靜態(tài)分配的數(shù)組的訪問越界問題。
為了使用它,首先請下載并安裝在你的系統(tǒng)上。可以使用操作系統(tǒng)上的包管理器來安裝。
使用命令行安裝需要解壓縮和解包下載的文件。
tar -xjvf valgring-x.y.z.tar.bz2 (where x.y.z is the version number you are trying to install)進入新創(chuàng)建的目錄(的valgrind-XYZ)內(nèi)運行以下命令:
./configuremakemake install讓我們通過一個小程序(test.c)來理解valgrind怎么工作的:
#include <stdio.h> void f(void) {int x = malloc(10 * sizeof(int)); x[10] = 0;} int main(){f();return 0;}編譯程序:
gcc -o test -g test.c現(xiàn)在我們有一個可執(zhí)行文件叫做'test'。我們現(xiàn)在可以用valgrind來檢測內(nèi)存錯誤:
valgrind –tool=memcheck –leak-check=yes test這是valgrind呈現(xiàn)錯誤的輸出:
valgrind顯示堆溢出和內(nèi)存泄漏的輸出
正如我們在上面看到的消息,我們正在試圖訪問函數(shù)f未分配的內(nèi)存以及分配尚未釋放的內(nèi)存。
5. GDB
GDB是來自自由軟件基金會的調(diào)試器。它對定位和修復(fù)代碼中的問題很有幫助。當被調(diào)試的程序運行時,它給用戶控制權(quán)去執(zhí)行各種動作, 比如:
啟動程序停在指定位置停在指定的條件檢查所需信息改變程序中的數(shù)據(jù) 等。你也可以將一個崩潰的程序coredump附著到GDB并分析故障的原因。
GDB提供很多選項來調(diào)試程序。 然而,我們將介紹一些重要的選擇,來感受如何開始使用GDB。
如果你還沒有安裝GDB,可以在這里下載:GDB官方網(wǎng)站。
編譯程序:
為了用GDB調(diào)試程序,必須使用gcc的'-g'選項進行編譯。這將以操作系統(tǒng)的本地格式產(chǎn)生調(diào)試信息,GDB利用這些信息來工作。
下面是一個簡單的程序(example1.c)執(zhí)行被零除用來顯示GDB的用法:
#includeint divide(){int x=5, y=0;return x / y;} int main(){divide();}
展示GDB用法的例子
調(diào)用 GDB:
通過在命令行中執(zhí)行'gdb'來啟動gdb:
調(diào)用 gdb
調(diào)用后, 它將等待終端命令并執(zhí)行,直到退出。
如果一個進程已經(jīng)在運行,你需要將GDB連接到它上面,可以通過指定進程ID來實現(xiàn)。假設(shè)程序已經(jīng)崩潰,要分析問題的原因,則用GDB分析core文件。
啟動程序:
一旦你在GDB里面,使用'run'命令來啟動程序進行調(diào)試。
給程序傳參數(shù):
使用'set args'給你的程序傳參數(shù),當程序下次運行時將獲得該參數(shù)。'show args'將顯示傳遞給程序的參數(shù)。
檢查堆棧:
每當程序停止,任何人想明白的第一件事就是它為什么停止,以及怎么停在那里的。該信息被稱為反向跟蹤。由程序產(chǎn)生每個函數(shù)調(diào)用和局部變量,傳遞的參數(shù),調(diào)用位置等信息一起存儲在堆棧內(nèi)的數(shù)據(jù)塊種,被稱為一幀。我們可以使用GDB來檢查所有這些數(shù)據(jù)。 GDB從最底層的幀開始給這些幀編號。
bt: 打印整個堆棧的回溯bt 打印n個幀的回溯frame : 切換到指定的幀,并打印該幀up : 上移'n'個幀down : 下移'n'個幀 ( n默認是1)檢查數(shù)據(jù):
程序的數(shù)據(jù)可以在里面GDB使用'print'命令進行檢查。例如,如果'x'是調(diào)試程序內(nèi)的變量,'print x'會打印x的值。
檢查list : 列出'linenum'行周圍的源碼list : 從'function'開始列出源碼disas : 顯示該函數(shù)機器代碼
停止和恢復(fù)程序:
使用GDB,我們可以在必要的地方設(shè)置斷點,觀察點等來停止程序。
break : 在'location'設(shè)置一個斷點。當在程序執(zhí)行到這里時斷點將被擊中,控制權(quán)被交給用戶。watch : 當'expr'被程序?qū)懭攵宜?#20540;發(fā)生變化時GDB將停止catch : 當'event'發(fā)生時GDB停止disable : 禁用指定斷點enable : 啟用指定斷點delete : 刪除 斷點/觀察點/捕獲點。 如果沒有傳遞參數(shù)默認操作是在所有的斷點step: 一步一步執(zhí)行程序continue: 繼續(xù)執(zhí)行程序,直到執(zhí)行完畢退出 GDB:
用'quit'命令還從GDB中退出。
GDB還有更多的可用選項。里面GDB使用help選項了解更多詳情。
在GDB中獲得幫助
總結(jié)
在這篇文章中,我們已經(jīng)看到不同類型的Linux用戶空間的調(diào)試工具。總結(jié)以上所有內(nèi)容,如下是什么時候使用該什么的快速指南:
基本調(diào)試,獲得關(guān)鍵變量 - print 語句獲取有關(guān)文件系統(tǒng)支持,可用內(nèi)存,CPU,運行程序的內(nèi)核狀態(tài)等信息 - 查詢 /proc 文件系統(tǒng)最初的問題診斷,系統(tǒng)調(diào)用或庫調(diào)用的相關(guān)問題,了解程序流程 – strace / ltrace應(yīng)用程序內(nèi)存空間的問題 – valgrind檢查應(yīng)用程序運行時的行為,分析應(yīng)用程序崩潰 – gdbvia: http://linoxide.com/linux-how-to/user-space-debugging-tools-linux/
作者:B N Poornima 譯者:mtunique 校對:wxy
本文由 LCTT 原創(chuàng)翻譯,Linux中國 榮譽推出
新聞熱點
疑難解答