gdb调试多线程和多进程

gdb调试多线程和多进程

一.多线程调试

代码

#include <thread>
#include <vector>
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
using namespace std;

int f1(int a, int b){ 
  int i = 0;
  while(true) {
    cout << "f1 : " << i << endl << endl;
    sleep(2);
    i++;
  }
  return 0;
}

int f2(int a, int b){ 
  int i = 0;
  while(true) {
    cout << "f2 : " << i << endl << endl;
    sleep(2);
    i++;
  }
  return 0;
}

void print() {
    cout << "HI" << endl << endl;
}

int f3(int a, int b){ 
  int i = 0;
  while(true) {
    cout << "f3 : " << i << endl << endl;
    print();
    sleep(2);
    i++;
  }
  return 0;
}

int main() {
  thread t1(f1, 1, 2); 
  thread t2(f2, 1, 2); 
  thread t3(f3, 1, 2); 
  while(1) 
  {
     printf("开始休眠两秒钟...\n\n");
     sleep(2);
  }

  return 0;
}

涉及到的gdb命令
set scheduler-locking [on|off|step]
当我们在一个线程中的代码打断点时,比如在第36行中打断点,程序运行到第36行时所有的线程都停住(断点会停住所有的线程)。继续运行时根据scheduler-locking的模式,运行命令会有不同的行为。
注意 : 和设置的断点一样step, next停住时,所有线程都停住
1.on模式
运行step, next和continue命令,只有t3线程运行,其他的线程都不运行。
2.off模式
运行step, next和continue命令,所有线程都运行。
3.step模式
运行step, next命令,只有t3线程运行;运行continue命令,所有线程都运行。

二.多进程调试

代码

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
  printf("本程序的进程编号是:%d\n",getpid());

  int ipid=fork();

  sleep(1);

  printf("pid=%d\n",ipid);

  while (true) {
      if (ipid!=0) {
        printf("父进程编号是:%d\n",getpid());
      }   
      else {
        printf("子进程编号是:%d\n",getpid());
      }   
      sleep(1);
  }

}

gdb调试一个进程,如果该进程fork/vfork了子进程,gdb会继续调试该进程,子进程并不受任何影响(比如在第17行打断点。父进程停住,但子进程会继续执行)。如果我们在子进程的代码处设置断点,子进程会收到SIGTRAP(5号信号,可以在linux系统中使用kill -l查询信号量)并终止,无法通过设置断点的方式调试子进程,那仫该如何调试子进程呢?在我的这篇文章中只介绍下面几种调试子进程的方法:follow-fork-mode,attach子进程方法。

1.follow-fork-mode

set follow-fork-mode [parent|child]

parent:gdb默认调试的是父进程,如果参数是parent则fork之后继续调试父进程,子进程不受影响,子进程会继续运行

child:如果想调试子进程,则修改参数为child,set follow-fork-mode child之后调试子进程,父进程不受影响。

show follow-fork-mode,查看当前调试的fork进程的模式

2.detach-on-fork

该参数表明gdb在fork之后是否断开(detach)某个进程的调试,或者交给gdb控制.

set detach-on-fork [on|off]

on:断开调试follow-fork-mode调试的指定进程

off:gdb将控制父进程和子进程。follow-fork-mode指定的进程将被调试,另一个进程置于暂停(suspended)状态。

show detach-on-fork,查看detach-on-fork模式

gdb将每一个被调试进程的执行状态记录在一个名为inferior的结构中。一般情况下一个inferior对应一个进程,每个不同的inferior有不同的地址空间。inferior有时候会在进程没有启动的时候就存在。

3.info inferiors

查询正在调试的进程,gdb会为他们分配唯一的Num号,其中前面带’*'号的就是正在调试的进程

4.inferior [inferior num]

切换调试的进程为inferior num的进程处

  1. add-inferior [-copies n] [-exec executable]

添加n个新的调试进程,可以用file executable来分配给inferior可执行文件。如果不指定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。删除前需要先kill或者detach这个inferior,因为当一个inferior正在运行时不能被删除.
10.set schedule-multiple [on|off]
off:只有当前inferior会执行。
on:全部是执行状态的inferior都会执行。
show schedule-multiple,查看schedule-multiple的状态。
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管理的地址空间的数目。

除了follow-fork-mode方法还有没有其他的方法调试多进程呢?我们知道gdb有附着(attach)到正在运行的进程的功能,即attach 命令。因此我们可以利用该命令attach到子进程然后进行调试。attach命令能够应付各种各样复杂的进程系统,比如孙子/曾孙进程,比如守护进程(精灵进程).

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值