蓝点工坊(http://www.bluedrum.cn) 创始人,App和嵌入式产品开发。同时也做相应培训和外包工作。 详细介绍 http://pan.baidu.com/s/1y2g88
全部博文(311)
分类: LINUX
2010-03-30 15:00:15
当你在程序中使用fork(),如果用gdb来调试.不管是你在子进程是否设置断点.你都只能在父进程单步调试,而没办法进入到子进程当中进行单步调试.因为gdb的所有处理(查看堆栈,内存,变量值)都是针对当前进程空间.
那么是否就没办法调试多进程程序的子进程代码呢?办法还是有的,一般的标准方法是再打开一个gdb用attach功能来调试子进程.gdb attach 功能是不执行被调试程序,而是把gdb“挂”到一个已经运行的进程之上来进行调试,这挂载的动作称为attach.当然也包括挂载子进程。
首先我们看一个如下简单的多进程程序。
/*
Author: Andrew Huang
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断点停下.
[root@localhost src]# gdb test_fork Breakpoint 2, main () at test_fork.c:41 parent [0] |
这时用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 Breakpoint 1, main () at test_fork.c:31 |
2.图形界面kdbg的调试
命令行界面gdb还是太麻烦了,一般我们还是采用界面前端来进行调试程序,一般用KDE自带KDbg最为方便.
2.1 首先用一个Kdbg打开程序
在图形界面设置断点,然后运行,可以看到主程序的断点已经进入并停下来了.
2.2 再打开一个kdbg,并且打开test_fork,设置好子进程的断点,选择主菜单的Execution->Attach,这时会出现如下界面,从进程列表选择子进程或用ps查到子进程ID直接输入即可