高能預警
本文主要介紹瞭如何使用linux環境下的代碼調試工具—gdb來調試多進程與多線程程序,主要內容有:
1. 問題引入
2. 調試方法介紹及代碼實例
3. gdb常用命令總結
4. 一些大神們關於此主題的介紹並附鏈接
——>全篇閱讀(不包括鏈接)大概需要8min<——
讀完本文後,你可以用簡單的方法調試多線程多進程程序。對幾種調試方法也會有一種宏觀認識。
問題引入
先來看一張圖:
圖中,Proc1通過調用fork函數產生子進程 Proc2,Proc2 又再次調用它產生子進程Proc3。這顯然是一個多進程程序。
但是,默認設置下,GDB不支持多進程程序調試。在調試多進程程序時GDB只會調試主進程,即proc1。例如,使用GDB調試某個進程,如果該進程fork了子進程,GDB會繼續調試該進程,子進程會不受干擾地運行下去。
注:GDB默認支持調試多線程
那麼問題來了,如何使用 GDB 調試子進程 proc2 或者 proc3 呢?
這就是本博文要講的主題。
方法介紹及代碼實例
總的來說,用gdb調試多進程與多線程有3種方法。
Solution1:follow-fork-mode
首先,這種方法對linux環境是有限制的:
在2.5.60版Linux內核及以後,GDB7.0版本以上的linux環境對使用fork/vfork創建子進程的程序提供了follow-fork-mode選項來支持多進程調試。
首先認識兩個選項:
follow-fork-mode(同步進程模式):這個模式有兩個選項:parent和child。默認值爲parent
detach-on-fork(分離進程):這個模式也有兩個選項:on和off 。默認值爲on
下面是他們各個選項組合所代表的含義:
從3和4可以看出,改變兩個選項設置調試多進程,實際上只是從宏觀上實現。同一時刻gdb只能操作一個進程,另一個進程只能被阻塞。
接下來通過代碼來看看選項的設置方法和具體的調試過程。
首先調試多進程:
Step1:查看是否達到環境要求
內核版本:
GDB版本:
可以看到,環境達到要求,所以可以進行操作。
Step2:編寫多進程代碼
首先看看fork函數的原型及返回值介紹:
編寫代碼:
運行代碼確保代碼編寫無誤:
Step3:開始調試
然後調試多線程:
Step1:編寫代碼
運行代碼保證代碼編寫無誤:
Solution2:Attach子進程
Solution3:GDB wrapper
很多時候,父進程 fork 出子進程,子進程會緊接着調用 exec族函數進行程序替換來執行新的代碼。對於這種情況,我們也可以使用gdb wrapper 方法。它的優點是不用添加額外代碼。
其基本原理是以gdb調用待執行代碼作爲一個新的整體來被exec函數執行,使得待執行代碼始終處於gdb的控制中,這樣我們自然能夠調試該子進程代碼。
這種方法可以參考文末的大神鏈接,博主技術太low,還不會實現。。。
小結
上述三種方法各有優缺點,因此適應於不同的場合和環境:
1.follow-fork-mode方法:方便易用,對系統內核和GDB版本有限制,適合於較爲簡單的多進程與多線程系統
2.attach子進程方法:靈活強大,但需要添加額外代碼,適合於各種複雜情況,特別是守護進程
3.GDB wrapper方法:專用於fork+exec模式,不用添加額外代碼,但需要X環境支持(xterm/VNC)
gdb常用命令總結
請移步:陳皓大神gdb調試系列
大神鏈接
1.3種方法綜合講解
IBM:使用 GDB 調試多進程程序
百度文庫:多進程 多線程調試方法 GDB調試 .
2.法1講解:
高科大神:gdb調試多進程和多線程命令