GDB多进程调试

内容来自牛客C++高薪面试项目2.5节,视频链接:https://www.nowcoder.com/study/live/504/2/5

命令简介

使用GDB 调试的时候,GDB 默认只能跟踪一个进程,可以在fork 函数调用之前,通过指令设置GDB 调试工具跟踪父进程或者是跟踪子进程,默认跟踪父进程。

  • 设置调试父进程或者子进程:set follow-fork-mode [parent(默认)| child]
  • 设置调试模式:set detach-on-fork [on | off]
    • 默认为on,表示调试当前进程的时候,其它的进程继续运行
    • 如果为off,调试当前进程的时候,其它进程被GDB 挂起。
  • 查看调试的进程:info inferiors
  • 切换当前调试的进程:inferior id
  • 使进程脱离GDB 调试:detach inferiors id

实例

  • 编译文件:gcc hello.c -o hello -g
  • 启动GDB调试:gdb hello
  • 分别在父进程和子进程里面打断点,并查看断点信息:
    (gdb) b 10
    Breakpoint 1 at 0x4006b9: file hello.c, line 10.
    (gdb) b 20
    Breakpoint 2 at 0x40070b: file hello.c, line 20.
    (gdb) i b
    Num     Type           Disp Enb Address            What
    1       breakpoint     keep y   0x00000000004006b9 in main at hello.c:10
    2       breakpoint     keep y   0x000000000040070b in main at hello.c:20
    
  • 启动调试程序,默认是对父进程代码进行的调试,使用 set follow-fork-mode child切换到子进程:
    (gdb) r
    Starting program: /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello 
    begin
    [Attaching after process 21220 fork to child process 21220]
    [New inferior 3 (process 21220)]
    [Detaching after fork from parent process 21219]
    [Inferior 2 (process 21219) detached]
    我是父进程:pid = 21219, ppid = 20241
    i = 0
    [Switching to process 21220]
    
    Breakpoint 2, main () at hello.c:20
    20              printf("我是子进程:pid = %d, ppid = %d\n", getpid(), getppid());
    (gdb) i = 1
    i = 2
    i = 3
    i = 4
    i = 5
    i = 6
    i = 7
    i = 8
    i = 9
    n
    我是子进程:pid = 21220, ppid = 1
    23              for(j = 0; j < 10; j++) {
    (gdb) n
    24                  printf("j = %d\n", j);
    (gdb) n
    j = 0
    25                  sleep(1);
    (gdb) n
    23              for(j = 0; j < 10; j++) {
    (gdb) n
    24                  printf("j = %d\n", j);
    (gdb) c
    Continuing.
    j = 1
    j = 2
    j = 3
    j = 4
    j = 5
    j = 6
    j = 7
    j = 8
    j = 9
    [Inferior 3 (process 21220) exited normally]
    
  • 在对子进程进行调试时,父进程是会继续运行的,使用 set detach-on-fork off挂起父进程:
    (gdb) set detach-on-fork off
    (gdb) r
    Starting program: /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello 
    begin
    [Attaching after process 22326 fork to child process 22326]
    [New inferior 4 (process 22326)]
    [Switching to process 22326]
    
    Breakpoint 2, main () at hello.c:20
    20              printf("我是子进程:pid = %d, ppid = %d\n", getpid(), getppid());
    Missing separate debuginfos, use: debuginfo-install glibc-2.17-323.el7_9.x86_64
    (gdb) n
    我是子进程:pid = 22326, ppid = 22325
    23              for(j = 0; j < 10; j++) {
    (gdb) n
    24                  printf("j = %d\n", j);
    (gdb) n
    j = 0
    25                  sleep(1);
    (gdb) n
    23              for(j = 0; j < 10; j++) {
    (gdb) n
    24                  printf("j = %d\n", j);
    (gdb) c
    Continuing.
    j = 1
    j = 2
    j = 3
    j = 4
    j = 5
    j = 6
    j = 7
    j = 8
    j = 9
    [Inferior 4 (process 22326) exited normally]
    
  • 使用 info inferiors查看当前调试的进程,并使用 inferior id切换到父进程,注意这里的id是 info inferiors显示出来的num:
    (gdb) r
    Starting program: /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello 
    begin
    [Attaching after process 22853 fork to child process 22853]
    [New inferior 5 (process 22853)]
    Reading symbols from /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello...done.
    [Switching to process 22853]
    
    Breakpoint 2, main () at hello.c:20
    20              printf("我是子进程:pid = %d, ppid = %d\n", getpid(), getppid());
    Missing separate debuginfos, use: debuginfo-install glibc-2.17-323.el7_9.x86_64
    (gdb) info inferiors 
      Num  Description       Executable  
    * 5    process 22853     /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello 
      4    process 22852     /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello 
      3    process 22325     /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello 
      2    <null>            /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello 
      1    <null>            /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello 
    (gdb) n
    我是子进程:pid = 22853, ppid = 22852
    23              for(j = 0; j < 10; j++) {
    (gdb) inferior 4
    [Switching to inferior 4 [process 22852] (/home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello)]
    [Switching to thread 3 (process 22852)] 
    #0  0x00007ffff7ad2a02 in fork () from /lib64/libc.so.6
    (gdb) n
    Single stepping until exit from function fork,
    which has no line number information.
    
    Breakpoint 1, main () at hello.c:10
    10              printf("我是父进程:pid = %d, ppid = %d\n", getpid(), getppid());
    (gdb) info inferiors 
      Num  Description       Executable  
      5    process 22853     /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello 
    * 4    process 22852     /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello 
      3    process 22325     /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello 
      2    <null>            /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello 
      1    <null>            /home/wzy1999/cpp/nowcoder/chapter02/lesson03-05/hello
    
  • 使用 detach inferiors id可以使进程脱离GDB调试,和continue的效果类似,进程执行完之后,Description会变成 <null>
posted @ 2023-01-27 18:28  友人-A  阅读(232)  评论(0编辑  收藏  举报