GDB 是 linux 系統上常用的 c/c++ 調試工具,功能十分強大。對於較爲複雜的系統,比如多進程系統,如何使用 GDB 調試呢?考慮下面這個三進程系統:
進程
Proc2 是 Proc1 的子進程,Proc3 又是 Proc2 的子進程。如何使用 GDB 調試 proc2 或者 proc3 呢?
實際上,GDB 沒有對多進程程序調試提供直接支持。例如,使用GDB調試某個進程,如果該進程fork了子進程,GDB會繼續調試該進程,子進程會不受干擾地運行下去。如果你事先在子進程代碼裏設定了斷點,子進程會收到SIGTRAP信號並終止。那麼該如何調試子進程呢?其實我們可以利用GDB的特點或者其他一些輔助手段來達到目的。此外,GDB 也在較新內核上加入一些多進程調試支持。
接下來我們詳細介紹幾種方法,分別是 follow-fork-mode 方法,attach 子進程方法和 GDB wrapper 方法。
follow-fork-mode
在2.5.60版Linux內核及以後,GDB對使用fork/vfork創建子進程的程序提供了follow-fork-mode選項來支持多進程調試。
follow-fork-mode的用法爲:
set follow-fork-mode [parent|child]
- parent: fork之後繼續調試父進程,子進程不受影響。
- child: fork之後調試子進程,父進程不受影響。
因此如果需要調試子進程,在啓動gdb後:
(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)狀態。
注意,最好使用GDB 6.6或以上版本,如果你使用的是GDB6.4,就只有follow-fork-mode模式。
follow-fork-mode/detach-on-fork的使用還是比較簡單的,但由於其系統內核/gdb版本限制,我們只能在符合要求的系統上才能使用。而且,由於follow-fork-mode的調試必然是從父進程開始的,對於fork多次,以至於出現孫進程或曾孫進程的系統,例如上圖3進程系統,調試起來並不方便。
Attach子進程
衆所周知,GDB有附着(attach)到正在運行的進程的功能,即attach <pid>命令。因此我們可以利用該命令attach到子進程然後進行調試。