萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 作業系統 >  >> Linux 教學

Linux 多進程程式 GDB 調試實戰:follow-fork-mode、attach PID 與 wrapper 三大核心技巧

多進程程式 (fork/exec) 調試是 Linux 系統程式開發的必修課。GDB 提供 follow-fork-mode、attach 與 wrapper 三種機制,配合 sleep() 同步技巧,可精準控制父/子進程調試流程。本文通過實戰範例逐一拆解。

核心概念:fork 後的調試選擇

進程 fork() 後產生父/子進程,GDB 預設繼續調試父進程,子進程自由運行。需透過設定決定跟蹤哪一側。

技巧一:follow-fork-mode + detach-on-fork

(gdb) set follow-fork-mode child   # 切換調試子進程 (parent/child)
(gdb) set detach-on-fork off       # 同時控制父子進程:被跟蹤者運行,另一者暫停
# on (預設):分離另一進程,不受 GDB 控制
# off:GDB 控制兩者,非當前跟蹤進程處於暫停狀態

適用場景:父子進程邏輯均需觀察,且不想修改程式碼。

技巧二:attach PID (動態附著子進程)

適用於子進程隨後 exec() 執行新程式,或需在特定時機介入調試。

前置準備:解決 Ubuntu GDB 權限問題

# 方案一:切換 root
sudo gdb ./program

# 方案二:賦予 gdb CAP_SYS_PTRACE (推薦)
sudo setcap cap_sys_ptrace=ep /usr/bin/gdb

實戰流程

  1. 在父/子進程程式碼最開頭加入同步等待:
volatile int pause_flag = 1;
while (pause_flag) sleep(1);
  1. 編譯並後台執行:./test &
  2. 查詢子進程 PID:
ps -ef | grep test
# 輸出範例:
# user 12345 12344  0 10:00 pts/0  00:00:00 ./test   ← 父進程
# user 12346 12345  0 10:00 pts/0  00:00:00 ./test   ← 子進程 (PID=12346)
  1. GDB 掛載子進程:
gdb -q ./test
(gdb) attach 12346
(gdb) set pause_flag = 0   # 釋放子進程繼續執行
(gdb) continue

技巧三:GDB Wrapper (適用 fork+exec 模式)

子進程 fork() 後緊接 exec() 載入新程式映像,GDB 可透過 wrapper 腳本自動攔截。

Wrapper 腳本範例 gdb-wrapper.sh

#!/bin/bash
# 由 GDB 呼叫: gdb --command=gdb-wrapper.sh --args ./parent_program
# 環境變數 GDB_WRAPPER=1 表示在 wrapper 內部

if [ -n "$GDB_WRAPPER" ]; then
    exec "$@"
else
    export GDB_WRAPPER=1
    exec gdb --command="$0" --args "$@"
fi

優點:無需修改原始碼加入 sleep();缺點:設定較複雜,需熟悉 GDB 腳本化。

進程前後台控制備忘

操作指令
後台執行./test &
暫停前台進程Ctrl+Z
恢復至後台bg %n (n 為 job number)
調回前台fg %n
查看任務jobs

GDB 多進程調試示意

總結:三大技巧各有優勢:follow-fork-mode 最簡單適合邏輯共享;attach 靈活適合動態介入;wrapper 適合 exec 替換映像場景。實戰中常組合使用,掌握核心指令即可從容應對複雜多進程調試。

copyright © 萬盛學電腦網 all rights reserved