使用GDB調試產生多進程的程序


如果一個進程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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM