4、GDB多进程调试
使用GDB 调试的时候,GDB默认只能跟踪一个进程;
可以在 fork 函数调用之前,通过指令设置GDB 调试工具跟踪父进程或者是跟踪子进程,默认跟踪父进程。
测试程序:hello.c:
#include <stdio.h>
#include <unistd.h>
int main() {
printf("begin\n");
if(fork() > 0) {
printf("我是父进程:pid = %d, ppid = %d\n", getpid(), getppid());
int i;
for(i = 0; i < 10; i++) {
printf("i = %d\n", i);
sleep(1);
}
} else {
printf("我是子进程:pid = %d, ppid = %d\n", getpid(), getppid());
int j;
for(j = 0; j < 10; j++) {
printf("j = %d\n", j);
sleep(1);
}
}
return 0;
}
编译:(调试后面加上 -g)
gcc hello.c -o hello -g
gdb打开hello
gdb hello
l: -- 查看代码
b: -- 加断点
ib: -- 查看所有断点信息
n: -- 向下继续执行
c: -- 将剩余的都执行完
4.1 GDB默认调试父进程
在第10行和20行都加一个断点;
默认直接跟踪父进程;
子进程默认直接执行结束,父进程停在断点处;
按n继续向下执行:
按c,将剩余的都执行完:
默认调试的是父进程,子进程代码会直接运行掉。
4.2 GDB调试子进程
show follow-fork-mode --查看跟踪的是父进程还是子进程
设置调试父进程或子进程:
set follow-fork-mode [parent(默认) | child]
设置调试子进程:
l查看代码,i b查看断点信息;
r进行执行:
父进程,默认执行结束,子进程还停在断点20行处
按n调试子进程:
4.3 设置调试模式
set detach-on-fork [on | off] --设置调试模式
show detach-on-fork --查看调试模式
- 默认为on,表示调试当前进程的时候,其它的进程继续运行;
- 如果为off,调试当前进程的时候,其它进程被GDB挂起。
默认为on的情况:
父进程,默认执行结束,子进程还停在断点20行处:
重新调试hello.c:
重新在第10行和20行打上断点:
可以看到默认调试的是父进程,调试模式是默认分离的(子 进程直接运行结束);
将调试模式设置为off:
此时按r,会停在父进程的断点处,子进程是不会向下执行的;
此时调试的都是父进程,
问:此时子进程在哪,子进程在fork的地方被挂起了;
info inferiors --查看调试的信息
此时会有两个进程,一个父进程,一个子进程;前面的*号,表示当前调试的进程;
在打开一个终端,输入ps -aux,可以查看到这两个进程信息;
inferior id --切换当前调试进程
切换到子进程:
inferior 2
调试子进程5636:
要先按c,让其到第二个断点处:
继续调试,可以打印j的值:
再切换回父进程:
直接将父进程执行完毕:
此时再次进程信息,发现父进程已经执行完了;
然后默认执行的就是子进程了:
detach inferiors id --使进程脱离开GDB调试
重新调试:
设置断点,设置调试子进程,默认off挂起状态;
调试之后,在切换调试父进程:
让父进程脱离GDB调试,继续向下执行:
最后quit退出。