【Linux】使用gdb调试多进程多线程程序

时间:2021-09-14 08:34:55

一、调试多进程
默认设置下,在调试多进程程序时GDB只会调试主进程。但是GDB(>V7.0)支持多进程的分别以及同时调试,换句话说,GDB可以同时调试多个程序。只需要设置follow-fork-mode(默认值:parent)和detach-on-fork(默认值:on)即可。

【Linux】使用gdb调试多进程多线程程序

设置方法: set follow-fork-mode [parent|child]
set detach-on-fork [on|off]

查询正在调试的进程:info inferiors
切换调试的进程: inferior
添加新的调试进程: add-inferior [-copies n] [-exec executable] ,可以用file executable来分配给inferior可执行文件。
其他:remove-inferiors infno, detach inferior

我们先编写多进程的代码,如下:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
void Child()
{
pid_t pid = getpid();
char str[] = "Child Process";
int count = 0;
while(count < 3)
{
printf("%s %u count =%d\n",str,pid,count);
count++;
}
}

void Father()
{
pid_t pid = getpid();
char str[] = "Father Process";
int count = 0;
while(count < 3)
{
printf("%s %u count =%d\n",str,pid,count);
count++;
}

}

int main()
{
gid_t id = fork();
if(id == 0)
{ //child
Child();
}
else if(id > 0)
{ //father
Father();
}
else
{
perror("fork");
exit(1);
}

return 0;

}

因为gcc默认编译程序是在Release版本,而要调试程序必须在Debug版本下,所以要对程序进行调试,记得在gcc编译时,在文件名后加上-g将其变为Debug版本的。
如:gcc -o test1 gdbtest1.c -g

gdb test1 打开调试文件,由于我们对父子进程同时调试,让gdb跟主进程,按照上面的方法,设置:set follow-fork-mode parent set detach-on-fork off

并在fork()函数处打断点
【Linux】使用gdb调试多进程多线程程序

在主进程单步执行一下,显示有新进程被创建,我们看一下正在调试的进程,有*代表跟进的是当前进程。因为之前让父子进程同时调试,gdb跟进主进程,所以此处的1号就是父进程。
【Linux】使用gdb调试多进程多线程程序

我们可以用 inferior 指令切换调试的进程,我们将调试的进程切换成子进程,如下。
【Linux】使用gdb调试多进程多线程程序

因为子进程执行Child函数,我们在Child函数那儿打断点观察,发现跳到了此处,证明当前确实是在调试子进程
【Linux】使用gdb调试多进程多线程程序

单步执行将子进程调试完(中间截图省略)
【Linux】使用gdb调试多进程多线程程序
【Linux】使用gdb调试多进程多线程程序

上图所示,子进程已经执行完毕,我们可以再切换回主进程,继续调试主进程即可。
【Linux】使用gdb调试多进程多线程程序

二、调试多线程

先给出多线程调试的代码示例:

#include<stdio.h>
#include<pthread.h>
void *id_run(void *arg)
{
printf("id%d run gdb success\n",(int )arg);
}

int main()
{
pthread_t pid1;
pthread_t pid2;
void* tmp;

pthread_create(&pid1,NULL,id_run,(void *)1);
pthread_create(&pid2,NULL,id_run,(void *)2);

pthread_join (pid1, &tmp);
pthread_join (pid1, &tmp);
return 0;
}

编译的时候记得一定要在后面加上链接库的名称 -lpthread
【Linux】使用gdb调试多进程多线程程序

下面来看一下调试多线程经常使用的命令:
【Linux】使用gdb调试多进程多线程程序

我们在创建线程函数pthread_create 处打下断点,设置单一线程调试set scheduler-locking on,单步执行一下,提示有新线程被创建。

【Linux】使用gdb调试多进程多线程程序

此时就有了两个线程,当前跟进的是主线程。我们要调试子线程,用thread ID ID命令切换当前调试的进程。
【Linux】使用gdb调试多进程多线程程序

我们在子线程调用函数出设置断点,发现跳到了此处,证明当前确实是在调试子线程
【Linux】使用gdb调试多进程多线程程序

将子线程2单步执行完,我们发现执行完线程2的时候,线程3随即被创建了,并且此时正在跟进线程3。我们也可以再切换回主线程。
【Linux】使用gdb调试多进程多线程程序

以上就是gdb调试多进程和多线程间的过程,如有错误,敬请指出。