首页 > 系统相关 >GDB调试多进程的命令介绍和演示

GDB调试多进程的命令介绍和演示

时间:2022-12-29 09:55:52浏览次数:48  
标签:fork multi 演示 process pid gdb GDB 进程 调试

命令汇总

命令 作用
info inferiors 查看所有进程
inferiors 2 切换到编号为2的进程
detach inferiors 2 detach掉编号为2的进程
kill inferiors 2 kill掉编号为2的进程
set follow-fork-mode parent 只调试父进程(GDB默认)
set follow-fork-mode child 只调试子进程
show follow-fork-mode 查看follow-fork-mode当前值
set detach-on-fork on 只调试一个进程,父进程或子进程(GDB默认)
set detach-on-fork off 同时调试父子进程,另一个进程阻塞在fork位置
show detach-on-fork 查看detach-on-fork当前值
set schedule-multiple off 只有当前进程会执行,其他进程挂起(GDB默认)
set schedule-multiple on 所有的进程都会正常执行
show schedule-multiple 查看schedule-multiple当前值

测试用例

/*================================================================
*  Author: LiuHanxu
*  Date: 2022-12-23
*  Description: how to debug multi-process by gdb
================================================================*/
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main()
{
    pid_t pid = fork();
    if(pid == 0) { // 子进程
        printf("I am child, my pid = %d, my parent pid = %d\n", getpid(), getppid());
    } else if(pid > 0) { // 父进程
        printf("I am parent, my pid = %d, my child pid = %d\n", getpid(), pid);
        wait(NULL); // 等待子进程退出
    } else {
       perror("fork error!\n");
       return -1;
    }
    return 0;
}

测试用例中一个是父进程,另一个是通过系统调用fork()创建的子进程。当fork()返回值为0说明当前在子进程里;返回值大于0说明在父进程里,此时返回值表示子进程的pid;返回值小于0说明fork时发生错误。

在默认情况下,在多进程程序中,GDB只调试主进程,也就是说无论程序调用了多少次fork()函数创建了多少个子进程,GDB在默认情况下,只调试父进程。

lhx@ubuntu:~/paopao-notes/code$ gdb ./test_multi_process 
Reading symbols from ./test_multi_process...
(gdb) run
Starting program: /home/lhx/paopao-notes/code/test_multi_process 
[Detaching after fork from child process 92666]
I am parent, my pid = 92663, my child pid = 92666
I am child, my pid = 92666, my parent pid = 92663
[Inferior 1 (process 92663) exited normally]
(gdb)

其中[Detaching after fork from child process xxx]则说明在fork出子进程后就释放了,只跟踪父进程。

进程操作命令inferiors

info inferiors查看所有进程,带*号表示当前进程。
inferiors 2切换到编号为2的进程。
detach inferiors 2detach掉编号为2的进程,注意这个进程还存在,可以再次用run命令执行它。
kill inferiors 2kill掉编号为2的进程,注意这个进程还存在,可以再次用run命令执行它。

Thread 1.1 "test_multi_proc" hit Breakpoint 1, main () at test_multi_process.c:16
16	        printf("I am parent, my pid = %d, my child pid = %d\n", getpid(), pid);
(gdb) i inferiors 
  Num  Description       Connection           Executable        
* 1    process 92828     1 (native)           /home/lhx/paopao-notes/code/test_multi_process 
  2    process 92831     1 (native)           /home/lhx/paopao-notes/code/test_multi_process 
(gdb) inferior 2
[Switching to inferior 2 [process 92831] (/home/lhx/paopao-notes/code/test_multi_process)]
[Switching to thread 2.1 (process 92831)]
#0  0x00007ffff7e9cf3f in fork () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) n
Single stepping until exit from function fork,
which has no line number information.
main () at test_multi_process.c:13
13	    if(pid == 0) { // 子进程
(gdb) n
14	        printf("I am child, my pid = %d, my parent pid = %d\n", getpid(), getppid());
(gdb) i inferiors 
  Num  Description       Connection           Executable        
  1    process 92828     1 (native)           /home/lhx/paopao-notes/code/test_multi_process 
* 2    process 92831     1 (native)           /home/lhx/paopao-notes/code/test_multi_process 
(gdb) kill inferiors 1
(gdb) i inferiors 
  Num  Description       Connection           Executable        
  1    <null>                                 /home/lhx/paopao-notes/code/test_multi_process 
* 2    process 92831     1 (native)           /home/lhx/paopao-notes/code/test_multi_process 
(gdb) detach inferiors 2
Detaching from program: /home/lhx/paopao-notes/code/test_multi_process, process 92831
[Inferior 2 (process 92831) detached]
I am child, my pid = 92831, my parent pid = 1
(gdb) i inferiors 
  Num  Description       Connection           Executable        
  1    <null>                                 /home/lhx/paopao-notes/code/test_multi_process 
* 2    <null>                                 /home/lhx/paopao-notes/code/test_multi_process 
(gdb) 

只调试子进程set follow-fork-mode child

set follow-fork-mode parent只调试父进程,子进程继续运行(GDB默认)。

set follow-fork-mode child只调试子进程,父进程继续运行。

show follow-fork-mode查看follow-fork-mode当前值

lhx@ubuntu:~/paopao-notes/code$ gdb ./test_multi_process 
Reading symbols from ./test_multi_process...
(gdb) show follow-fork-mode 
Debugger response to a program call of fork or vfork is "parent".
(gdb) list 14
9	
10	int main()
11	{
12	    pid_t pid = fork();
13	    if(pid == 0) { // 子进程
14	        printf("I am child, my pid = %d, my parent pid = %d\n", getpid(), getppid());
15	    } else if(pid > 0) { // 父进程
16	        printf("I am parent, my pid = %d, my child pid = %d\n", getpid(), pid);
17	        wait(NULL); // 等待子进程退出
18	    } else {
(gdb) b 14
Breakpoint 1 at 0x1204: file test_multi_process.c, line 14.
(gdb) r
Starting program: /home/lhx/paopao-notes/code/test_multi_process 
[Detaching after fork from child process 92674]
I am parent, my pid = 92671, my child pid = 92674
I am child, my pid = 92674, my parent pid = 92671
[Inferior 1 (process 92671) exited normally]
(gdb) 
(gdb) set follow-fork-mode child 
(gdb) r
Starting program: /home/lhx/paopao-notes/code/test_multi_process 
[Attaching after process 92675 fork to child process 92676]
[New inferior 2 (process 92676)]
[Detaching after fork from parent process 92675]
[Inferior 1 (process 92675) detached]
I am parent, my pid = 92675, my child pid = 92676
[Switching to process 92676]

Thread 2.1 "test_multi_proc" hit Breakpoint 1, main () at test_multi_process.c:14
14	        printf("I am child, my pid = %d, my parent pid = %d\n", getpid(), getppid());
(gdb) n
I am child, my pid = 92676, my parent pid = 92675
22	    return 0;
(gdb) 

通过上面测试发现,当保持gdb默认值时,只调试父进程。当在14行子进程里设断点后,发现程序不会停住。将follow-fork-mode设为child后,父进程继续执行,而此时子进程能够停在断点处。

同时调试父子进程set detach-on-fork off

set detach-on-fork on只调试一个进程,可以是父进程或子进程(GDB默认)。

set detach-on-fork off同时调试父子进程,如果follow-fork-mode是parent,则gdb跟踪父进程,子进程阻塞在fork位置。如果follow-fork-mode是child,则gdb跟踪子进程,父进程阻塞在fork位置。此时用户可以根据调试情况在父进程和子进程之间来回切换调试。

show detach-on-fork查看detach-on-fork当前值。


lhx@ubuntu:~/paopao-notes/code$ gdb ./test_multi_process 
Reading symbols from ./test_multi_process...
(gdb) set follow-fork-mode child 
(gdb) set detach-on-fork off
(gdb) b 14
Breakpoint 1 at 0x1204: file test_multi_process.c, line 14.
(gdb) b 16
Breakpoint 2 at 0x122d: file test_multi_process.c, line 16.
(gdb) r
Starting program: /home/lhx/paopao-notes/code/test_multi_process 
[Attaching after process 92736 fork to child process 92739]
[New inferior 2 (process 92739)]
[Switching to process 92739]

Thread 2.1 "test_multi_proc" hit Breakpoint 1, main () at test_multi_process.c:14
14	        printf("I am child, my pid = %d, my parent pid = %d\n", getpid(), getppid());
(gdb) n
I am child, my pid = 92739, my parent pid = 92736
22	    return 0;
(gdb) i inferiors 
  Num  Description       Connection           Executable        
  1    process 92736     1 (native)           /home/lhx/paopao-notes/code/test_multi_process 
* 2    process 92739     1 (native)           /home/lhx/paopao-notes/code/test_multi_process 
(gdb) inferior 1
[Switching to inferior 1 [process 92736] (/home/lhx/paopao-notes/code/test_multi_process)]
[Switching to thread 1.1 (process 92736)]
#0  0x00007ffff7e9cf3f in fork () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) c
Continuing.

Thread 1.1 "test_multi_proc" hit Breakpoint 2, main () at test_multi_process.c:16
16	        printf("I am parent, my pid = %d, my child pid = %d\n", getpid(), pid);
(gdb) n
I am parent, my pid = 92736, my child pid = 92739
17	        wait(NULL); // 等待子进程退出
(gdb)

上面测试用例中,通过set follow-fork-mode childset detach-on-fork off设置为gdb跟踪子进程,父进程阻塞在fork位置。然后切换到父进程,继续运行父进程。

所有进程同步执行set schedule-multiple on

在调试多进程时,默认情况下,除了当前调试的进程,其他进程都处于挂起状态,所以,如果需要在调试当前进程的时候,其他进程也能正常执行,那么通过设置set schedule-multiple on即可。

set schedule-multiple offgdb发出执行命令后,只有当前进程会执行,其他进程挂起(GDB默认)。

set schedule-multiple on当gdb发出执行命令后,所有的进程都会正常执行。

show schedule-multiple查看schedule-multiple当前值。

调试截图演示

image-20221223220628497

image-20221223220654378

image-20221223220731646

标签:fork,multi,演示,process,pid,gdb,GDB,进程,调试
From: https://www.cnblogs.com/liuhanxu/p/17011777.html

相关文章

  • Windows Service调试方法小结
    方法1:log记录这是一个通用的调试方法,效率比较低,但比较实用,通过查看日志,总能达到调试的目的方法2:附加到进程这是WindowsService程序调试的常用方法,缺点是对Windows环境......
  • 修改内核源码绕过反调试检测(Android10)
    一、Android反调试     反调试在代码保护中扮演着非常重要的角色,虽然不能完全阻止攻击者,但是能加大攻击者的分析时间成本。目前绝大多数Androidapp都加固了,为了防......
  • 【开源】基于.net6+gtksharp实现的Linux下的图形界面串口调试工具
    背景参考okeyl.com22年初从上家互联网公司离职以后,充分认识到互联网行业的风险,公司在没有自身稳定产品的情况下,互联网行业就是一个烧钱的行业,支出远远大于收入来......
  • 如何对生产环境的JAVA应用进行远程调试
    JAVA自身支持调试功能,并提供了一个简单的调试工具--JDB,类似于功能强大的GDB,JDB也是一个字符界面的调试环境,并支持设置断点,支持线程线级的调试。 1.在服务器上的进程启动参数......
  • 20221227ping命令+格西调试精灵的使用
      先用格西调试精灵,”通信接口“连接后才能ping通 ping是什么?ping就是windows、Unix或者Linux系统下达的一个命令,也可以说是一个通信协议,并且是TCP/IP协议的一......
  • 我是怎么调试 Element UI 源码的
    ​​上篇文章​​写了怎么调试antd的源码,反响很不错:但很多小伙伴是写Vue的,可能平时用的是ElementUI的组件库,所以这篇文章就来讲下怎么调试ElementUI的源码。首先,......
  • 【开源】基于.net6+gtksharp实现的Linux下的图形界面串口调试工具
    背景22年初从上家互联网公司离职以后,充分认识到互联网行业的风险,公司在没有自身稳定产品的情况下,互联网行业就是一个烧钱的行业,支出远远大于收入来源,上家公司就是如......
  • GDB调试精粹及使用实例
    一:列文件清单 1.List (gdb)listline1,line2 二:执行程序 要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明......
  • Camera 画质调试,学习资料分享
    “  最近有很多小伙伴私信我有没有 Camera 相关的学习资料,所以这里总结了一下,我目前看到及学习过的觉得比较优质的资料,大家可以收藏学习起来。注意下文章中的链接无法直......
  • ISP调试流程概述
    概要:本文主要是整理了一下,关于isp效果调试的工作中,我们平常在接到一个项目任务时,一般都需要做哪些事情;首先我们要明白,作为一个合格的tuning工程师,在调测一款相机的效果时,是......