linux下用gdb调试多进程

来源:互联网 发布:linux修改文件命令 编辑:程序博客网 时间:2024/05/22 19:00

今天来学习一下linux下gdb如何调试多进程,在学习之前我我们能先看一张表:
这里写图片描述
这张表是gdb调试的命令表,这对那些对gdb不熟的同学来说是非常有必要的。
一、多进程调试的命令
1、set follow-fork-mode parent|child
因为gdb在一般情况下,只会调试主进程。这条命令就可以使gdb来实现多进程的调试,进入gdb后默认调试的是parent,要想调试child的话,需要设置set follow-fork-mode child,然后进入调试。当然这种方式只能同时调试一个进程。
show follow-fork-mode就是查看当前调试的fork的模式。
2、detach-on-fork on|off:
设置为on,只调试父进程或子进程其中一个,需要根据follow-fork-mode决定,这是默认模式。
设置成off,父子进程都在gdb的控制之下,其中一个进程正常调试,需要根据follow-fork-mode决定,另一个进程会被设置为暂停状态。
GDB将每一个被调试程序的执行状态记录在一个名为inferior的结构中。一般情况下一个inferior对应一个进程,每个不同的inferior有不同的地址空间。inferior有时候会在进程没有启动的时候就存在。
3、info inferiors:
这条语句是为了显示GDB调试的所有inferior,GDB会为他们分配ID。其中带有*的进程是正在调试的inferior。
4、inferior num:
切换需要调试的进程的id
5、add-inferior [-copies n] [-exec executable]:
增加n个inferior并执行程序为executable。如果不指定n只增加一个inferior。如果不指定executable,则执行程序留空,增加后可使用file命令重新指定执行程序。这时候创建的inferior其关联的进程并没启动。
6、clone-inferior [-copies n] [infno]:
复制n个编号是infno的inferior。如果不指定n的话,就只复制一个inferior。如果不指定infno,则就复制正在调试的inferior。
7、detach inferior infno:
detach掉编号是infno的inferior。注意这个inferior还存在,可以再次用run命令执行它
8、kill inferior infno:
kill掉infno号inferior。注意这个inferior仍然存在,可以再次用run等命令执行它
9、remove-inferior infno:
删除一个infno号的inferior。如果inferior正在运行,则不能删除,所以删除前需要先kill或者detach这个inferior
10、set schedule-multiple on|off:
设为off:只有当前inferior会执行。
设为on:全部是执行状态的inferior都会执行。
这个选项类似于多线程调试里的set scheduler-locking选项
如果scheduler-locking是指为on,即使schedule-multiple设置为on,也只有当前进程的当前线程会执行。
11、set follow-exec-mode new|same:
设置same:当发生exec的时候,在执行exec的inferior上控制子进程。
设置为new:新建一个inferior给执行起来的子进程。而父进程的inferior仍然保留,当前保留的inferior的程序状态是没有执行。
show follow-exec-mode:查看follow-exec-mode设置的模式。
12、set print inferior-events on|off:用来打开和关闭inferior状态的提示信息。
show print inferior-events :查看print inferior-events设置的状态。
13、maint info program-spaces:
用来显示当前GDB一共管理了多少地址空间。

二、多进程的代码

#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<sys/type.h>#include<sys/wait.h>int main(){    pid_t id = fork();    if(id < 0)    {        perror("fork error!");        return -1;    }    else if(id == 0)    {        printf("child is: %d,father is: %d\n",getpid(),getppid());    }    else    {        sleep(1);        printf("father is :%d\n",getpid());        wait(NULL);    }    return 0;}

三、调试情况
在编译的时候别忘了加上 -g(我刚开始就是犯了这样的错……)
1、设置调试的模式:
这里写图片描述
2、这是查看两个进程的情况:
这里写图片描述
如果大家需要切换要调试的进程可以使用上面我们提到过得命令:inferior 进程id这样就可以切换者调试其他的进程了。
注意:我们看见的进程前的*号,就表示当前正在调试的进程。