之前我们介绍了gdb调试的相关命令与操作gdb调试命令,下面我们再来了解一下如何用gdb调试多进程。
事实上真正在运用上并不是只有一个进程在运行,多进程的方式能够达到很好的效率。gdb也可以调试多进程,但是在默认情况下,gdb只会调试主进程。但是通过设置参数follow-fork-mode(默认值为parent)和detach-on-fork(默认值为on)就可以调试多进程程序,这两个参数的意思如下
follow-fork-mode detach-on-fork 情况 parent on 只调试父进程 child on 只调试子进程 parent off 同时调试父进程和子进程,gdb跟父进程,子进程在fork位置 child off 同时调试父进程和子进程,gdb跟子进程,父进程在fork位置
下面给一段代码来调试多进程程序
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> int main() { pid_t pid=fork();//创建子进程 if(pid < 0) { perror("fork"); return -1; } else if(pid == 0)//子进程 { printf("I am child:My pid is %d,my father's pid is %d\n",getpid(),getppid()); } else//父进程 { printf("I am father:My pid is %d\n",getpid()); wait(NULL);//等待子进程 } return 0; }
使用gdb开始调试程序,需要在编译的时候加上-g选项。
1 .首先,查看一下系统当前默认的两个参数的值
2 .用list命令列出源代码,分别在父子进程的开始处下一个断点
3 .当前的默认两个参数的默认值是parent和on,意思是只调试父进程,我们将follow-fork-mode的参数改为child,将detach-on-fork的参数改为off,意思是同时调试父子进程,让gdb跟子进程,父进程在fork处
4.运行程序,查看正在调试的进程
蓝色框部分表示这是一个新进程2833,即子进程的pid,红色框部分是下一句要执行的代码
info inferiors命令:gdb将每一个进行调试的程序记在inferiors中,并分给它们ID,可以通过info inferiors命令来查看gdb调试的进程,带有*的进程是正在调试的进程。
输入c(continue)命令继续调试程序
子进程运行完,并退出。
5.切换调试的程序,并运行
父进程运行完,并退出。
可以看到现在已经没有进程了。
6.其余相关命令
- add-inferior [-copies <N>] [-exec <FILENAME>]加入一个新的inferior,N是可用的inferior的ID,默认为1;FILENAME是一个可执行程序的文件名
- remove-inferior ID 删除一个inferior,不能是正在被调试的inferior
- clone-inferior [-copies <N>] [ID] 复制N个编号是ID的inferior。如果不指定N的话,默认复制一个inferior。如果不指定ID,则默认复制正在调试的inferior
- detach inferior 分离出一个ID编号的inferior,这个inferior仍旧可以被执行,还存在。
- kill inferior 杀死一个ID编号的inferior,这个inferior仍旧可以被执行,还存在。
注意看一下kill和detach的区别
注意看红色部分,detach子进程之后,子进程还是输出了,即子进程还是跑完了,但是kill子进程之后,什么都没有输出,即直接跳过了,这个地方的区别需要注意一下。当然了,他们都还是可以继续run的,如果想要删除用remove_inferior。
- set schedule_multiple on|off 设为off,只有当前inferior会执行;设为on,所有在执行状态的inferior都会执行
- set follow-exec-mode same|new 设置same:当发生exec的时候,在执行exec的inferior上控制子进程;
设置为new:新建一个inferior给执行起来的子进程,而父进程的inferior仍然保留,当前保留的inferior的程序状态是没有执行。 - set print inferior-events on|off 用来打开和关闭inferior状态的提示信息
- maint info program-spaces 查看gdb一共管理了多少地址空间