Linux 下用gdb单步调试多进程方法

    技术2022-05-19  21

    ps -ef|grep ./my_main|grep -v grep| cut -c 9-15|xargs kill; 当你在程序中使用fork(),如果用gdb来调试.不管是你在子进程是否设置断点.你都只能在父进程单步调试,而没办法进入到子进程当中进行单步调试.因为gdb的所有处理(查看堆栈,内存,变量值)都是针对当前进程空间.

    当你在程序中使用fork(),如果用gdb来调试.不管是你在子进程是否设置断点.你都只能在父进程单步调试,而没办法进入到子进程当中进行单步调试.因为gdb的所有处理(查看堆栈,内存,变量值)都是针对当前进程空间.

    那么是否就没办法调试多进程程序的子进程代码呢?办法还是有的,一般的标准方法是再打开一个gdb用attach功能来调试子进程.gdb attach 功能是不执行被调试程序,而是把gdb“挂”到一个已经运行的进程之上来进行调试,这挂载的动作称为attach.当然也包括挂载子进程。

    首先我们看一个如下简单的多进程程序。

     

    /*   Author: Andrew Huang bluedrum@163.com   debug multi-process by gdb. */ #include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #define PRINT_INT(e) printf("%s=%d/n",#e,e) int main() {   pid_t pid;   int i,val = 100;      printf("process id %d/n",getpid());        pid = fork();      PRINT_INT(val);      if(pid == 0)   {/* child process */          val+=100;     printf("child process id %d,parent id %d/n",getpid(),getppid());          PRINT_INT(val);          i = 0;          while(1)     {       printf("child [%d]/n",i++);       sleep(1);     }   }   else if(pid >0)   {/* parent child */      printf("parent process id %d/n",getpid());           for(i=0 ; i < 5 ; i++)     {       printf("parent [%d]/n",i);     }            val+=10;            PRINT_INT(val);             wait(NULL);               }   else /* error */   {    exit(-1);   }         PRINT_INT(val);      return 0; }

     

    这个程序很简单,就是子进程在无限循环打印屏幕,而父进程在用wait等待.

    编译 gcc test_fork.c -o test_fork -g

    1.双gdb调试

    首先用常规方法gdb test_fork.c 调试程序,分别在31行,41行设断点,然后用run执行程序,可以看到gdb在41行父进程的断点停下来.但是子进程在自行执行,无法在31断点停下.

     

    这时用gdb attach功能来调试子进程,首先用ps -aux | grep test_fork 找出子进程号.

    然后用 gdb test_fork <进程号>挂入已经知进程.这时就可以看到在子进程的断点可以停下来,而且父进程的gdb窗口里,子进程输出停下并受子进程的gdb控制,这里你可以用常规调试手段来看程序了.(如看memory,watch,stack等)

    操作步骤,进入gdb首先用b 31 设置子进程中断点.然后用c(这里要用continue,因为attach的进程已经在运行了,不能用run)

    然后可以看到断点在生效了.至此可以常规调试方法即可

     

    [root@localhost src]# ps -aux | grep test_fork Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.7/FAQ root      3957  0.0  0.2  11012  4824 pts/7    S+   13:18   0:00 gdb test_fork root      3959  0.0  0.0   1516   328 pts/7    T    13:19   0:00 /home/hxy/src/test_fork root      3962  0.0  0.0   1516   280 pts/7    S    13:19   0:00 /home/hxy/src/test_fork root      3985  0.0  0.0   5020   672 pts/9    R+   13:19   0:00 grep test_fork [root@localhost src]# gdb test_fork 3962 GNU gdb Fedora (6.8-27.el5) Copyright (C) 2008 Free Software Foundation, Inc. (gdb) b 31 Breakpoint 1 at 0x8048541: file test_fork.c, line 31. (gdb) c Continuing.

    Breakpoint 1, main () at test_fork.c:31 31            printf("child [%d]/n",i++); (gdb) n 32            sleep(1); (gdb) n 33          } (gdb)

     

    2.图形界面kdbg的调试

    命令行界面gdb还是太麻烦了,一般我们还是采用界面前端来进行调试程序,一般用KDE自带KDbg最为方便.

    2.1 首先用一个Kdbg打开程序

    在图形界面设置断点,然后运行,可以看到主程序的断点已经进入并停下来了.

    2.2 再打开一个kdbg,并且打开test_fork,设置好子进程的断点,选择主菜单的Execution->Attach,这时会出现如下界面,从进程列表选择子进程或用ps查到子进程ID直接输入即可

     

     

      2.3 此时两个kdbg在同时调一个程序不同进程,注意所有标准输入输出都发生在调试主进程的kdbg的终端窗口里

    来自:http://blog.chinaunix.net/u3/105675/showart_2205274.html

     

    [root@localhost src]# gdb test_fork GNU gdb Fedora (6.8-27.el5) (gdb) b 31 Breakpoint 1 at 0x8048541: file test_fork.c, line 31. (gdb) b 41 Breakpoint 2 at 0x804858e: file test_fork.c, line 41. (gdb) r Starting program: /home/hxy/src/test_fork process id 3959 Detaching after fork from child process 3962. val=100 parent process id 3959

    Breakpoint 2, main () at test_fork.c:41 41            printf("parent [%d]/n",i); (gdb) val=100 child process id 3962,parent id 3959 val=200 child [0] child [1] child [2] child [3] child [4] child [5] child [6] child [7] nchild [8] child [9]

    parent [0] 39          for(i=0 ; i < 5 ; i++) (gdb) child [10] n

     


    最新回复(0)