1. 程式人生 > >使用GDB調試多進程

使用GDB調試多進程

pen style 繼續 follow exe lin c函數 exec color

如果一個進程fork了多個進程,這時使用GBD工具對程序進行調試會如何呢?

實際上,GDB 沒有對多進程程序調試提供直接支持。例如,使用GDB調試某個進程,如果該進程fork了子進程,GDB會繼續調試該進程,子進程會不受幹擾地運行下去。

如果你事先在子進程代碼裏設定了斷點,子進程會收到SIGTRAP信號,如果沒有對此信號進行捕捉處理,就會按默認的處理方式處理——終止進程。

那麽該如何調試子進程呢?有3種方法:


1.follow-fork-mode

在2.5.60版Linux內核及以後,GDB對使用fork/vfork創建子進程的程序提供了follow-fork-mode選項來支持多進程調試:

follow-fork-mode的用法為:

set follow-fork-mode [parent|child]

  parent:調試父進程,子進程不受影響

  child:調試子進程,父進程不受影響

我們需要調試子進程,所以在啟動gdb後,輸入命令

set follow-fork-mode child

並在子進程代碼處設置斷點。此外還有detach-on-fork參數,指示GDB在fork之後是否斷開(detach)某個進程的調試,或者都交由GDB控制:

set detach-on-fork [on | off]

  on: 斷開調試follow-fork-mode指定的進程。

  off: gdb將控制父進程和子進程。follow-fork-mode指定的進程將被調試,另一個進程置於暫停(suspended)狀態。

這兩種模式支持需要GDB6.6及以上版本。由於follow-fork-mode的調試必然是從父進程開始的,對於fork多次,以至於出現孫進程或曾孫進程的系統,調試起來並不方便。


2.Attach子進程

GDB有附著(attach)到正在運行的進程的功能,即attach <pid>命令。因此我們可以利用該命令attach到子進程然後進行調試。

首先,要獲得進程的ID,終端中使用命令:

ps -ef | grep YOUR_PROCESS_NAME

然後進入gdb使用命令

attach pid

現在可以調試了。但是如果子進程一直在運行,那麽attach上之後就不知道運行到哪裏去了。一個辦法是,在剛剛進入子進程程序段時加入一段睡眠程序,即調用sleep函數,使子進程進入一定時間的睡眠狀態,確保在子進程睡眠狀態結束之前要attach上子進程,之後在子進程代碼段設置斷點,然後就可以對子進程進行調試了。

Attach進程方法還是很方便的,它能夠應付各種各樣復雜的進程系統,比如孫子/曾孫進程,比如守護進程(daemon process),唯一需要的就是加入一小段代碼。


3.GDB wrapper

很多時候,父進程 fork 出子進程,子進程會緊接著調用 exec族函數來執行新的代碼。對於這種情況,我們也可以使用gdb wrapper 方法。它的優點是不用添加額外代碼。

其基本原理是以gdb調用待執行代碼作為一個新的整體來被exec函數執行,使得待執行代碼始終處於gdb的控制中,這樣我們自然能夠調試該子進程代碼。

這個方法適合fork+exec模式,需要需要X環境支持(xterm/VNC)。


參考資料:

https://www.ibm.com/developerworks/cn/linux/l-cn-gdbmp/

使用GDB調試多進程