linux下多进程的调试

linux下多进程的调试
碰到多进程的程序如何调试呢?默认情况下,你next下来,跟的路径都是主进程的,而你想跟的子进程路径没跑到?怎么办呢?有几种方法,今天看了看attach方法,觉得不错,特记录如下:原理:运行多进程程序,得到要跟的子进程的ID;然后用开gdb,用attach+ID,然后stop,为什么要stop?防止子进程自己跑完,所以要stop,然后可以设断点,观测点,什么的。设完后,可以step,下一步,向下跟。 主要原理是这样。下面举个例子:#include<stdio.h>
                                                                               
int main()
{
        if(fork() == 0)
        {
                int b = 9;
                sleep(60);
                int a =1;
                int c = 90;
                int d =5;
                printf("child\n");
        }
        else
        {
                wait(NULL);
                printf("parant\n");
        }
        return 0;
}怎么样跟到子进程里面去 ?1 后台运行该程序,可以得到进程ID2 gdb下,attach+id3 stop,然后设置断点,观察点等等4 step (gdb) attach 12606
Attaching to program: /home/purerain/test/f, process 12606
Symbols already loaded for /lib/tls/libc.so.6
Symbols already loaded for /lib/ld-linux.so.2
0xffffe002 in ?? ()
(gdb) stop
(gdb) b 12
Breakpoint 8 at 0x8048402: file fork.c, line 12.
(gdb) c
Continuing.


Breakpoint 7, main () at fork.c:11
11                      int d =5;
(gdb) s
12                      printf("child\n");
(gdb) s
19              return 0;
(gdb) s
20      }
(gdb) s
0x42015574 in __libc_start_main () from /lib/tls/libc.so.6
(gdb) s
Single stepping until exit from function __libc_start_main,
which has no line number information.


Program exited normally.              


Linux下的C语言多进程调试问题


在Linux下使用C语言开发程序是比较头疼的问题,用Eclipse进行开发的过程中,对于多进程的调试一直是一个为解决的问题。
由于Eclipse的DBG调试器好像没有直接提供多进程的调试功能,所以在进行网络变成种涉及的多进程的调试问题显得很棘手。
经过网络上的查找,发现在Linux下面进行多进程的调试最好的工具还是GDB。GDB可以通过Attach命令加载进程,从而进行调试。
总结一下,通常在Linux下调试C语言的多进程主要有这样几个办法:


1、可以在你的程序中修改你的fork函数,如:
if((pid = fork())==0){
    //子进程
}else{
//父进程
}       
如果在Eclipse里面用DBG直接进行步进调试,则程序会在后台执行子进程的部分,在前台只能挑试父进程的部分。为了调试子进程,可以把程序改写为
(pid = fork())〉0,
这样程序就改变了原来的父子进程之间的关系,原来子进程部分的代码变成了父进程进行运行,从而可以步进调试。
但是这样做会带来许多意想不到的潜在危险,最好调试的时候只执行一次,
否则可能会有意外发生。而且对于多个子进程以及多极子进程的程序的调试同样是很费事很容易出错的。       


2、可以有关gdb调试器的Attach命令对已经运行的程序进行加载调试。不过这种做法同样要改变远程序中的内容,只是改变的程度要小很多,副作用也小很多而已。通常的做法是:       在进程创建的过程中,在子进程中加入一下一些代码:
if((pid = fork())==0){                //子进程               
 int pause = 1;  //可以理解为一个开关                  
 while(pause)               
 {                sleep(1);
 //程序睡眠的时间多少并不重要,这个是用来放置程序不停的循环时过多地   
 //占用进程资源               return 0;             
 }      ...     
 }                 
 
这样在程序的int pause... 部分创建断点,在调试的过程中,会提示系统Detaching ...,这其实是制定了子进程的pid号码,也可以在终端中调用ls -ef查看子进程的进程号,接着调用Attach命令加载进程号。当进程挂起在断点的时候,我们可以改变pause的指位0,从而跳过循环过程,重新执行子进程中的内容。这里要注意的一个地方是子进程中的结尾部分要有return 0 语句(如果你的函数定义的是类似
int func(...)),
这样gdb在调试中Detach的时候可以自动结束或挂起进程,否则系统就会一直等在那里,我们什么都做不了了。       3、第三种方法适用于比较高版本的GDB(如6.0以上的版本),我们可以在调试程序的过程中在进程fork()以前设置断点,进行步进调试,在需要fork()的之前使用命令:
       set follow-fork-mode child | parent       
  
如果选择child,则调试程序自动的Detach 父进程,接着Attach 子进程,这些都是自动完成的,只是同样要注意第二点中提到的return的问题。其实在这里我们可以自由的选择是进行父进程还是子进程的调试。而且在程序可一直步进的调试下去,直到下一个fork的出现,我们再一次的进行选择。感觉这个方法比较实用,是比较不错的方法。

你可能感兴趣的:(linux下多进程的调试)