fork 多进程调试

本文介绍了使用GDB调试多进程的三种方法:1) follow-fork-mode,用于选择跟踪父进程或子进程;2) detach-on-fork mode,控制调试父进程或子进程并决定是否暂停另一个进程;3) attach方式,在子进程启动后手动附加调试。通过实例代码解释了如何设置断点和使用这些模式,并提供了在不同场景下的应用示例。
摘要由CSDN通过智能技术生成

实例代码


  1 #include <unistd.h>
  2 #include <stdio.h> 
  3 int main () 
  4 { 
  5     pid_t fpid;
  <span style="color:#3333ff;">6     printf("aaaaaaaaaaaaaaaaaa!\n");</span>
  7     fpid=fork(); 
  8     printf("bbbbbbbbbbbbbbbbbb!\n");
  9     if (fpid < 0) 
 10         printf("error in fork!\n");
 11     else if (fpid == 0) {
<span style="color:#3333ff;"> 12         printf("i am the child process, my process id is %d\n",getpid());</span>
 13     } else {
<span style="color:#3333ff;"> 14         printf("i am the parent process, my process id is %d, my child process id is %d\n",getpid(), fpid);</span>
 15     }   
 16     return 0;
 17 }  

fork多进程调试一般有一下3种方法:


1. follow-fork-mode
用法:set follow-fork-mode [parent|child] 
进入gdb后,直接设置,默认是parent
所以如果想要调试子进程,进入gdb后设置set follow-fork-mode child,然后设置子进程的断点
可用使用show follow-fork-mode 来查询当前fork模式
如果在6.12.14行加断点,r后会停在6行处

使用follow-fork-mode,只能调试一个进程,不能同时调试父子进程

2. detach-on-fork mode
用法:set detach-on-fork [on|off]
on: 只调试父进程或子进程的其中一个(根据follow-fork-mode来决定),这是默认的模式。
off: 父子进程都在gdb的控制之下,其中一个进程正常调试(根据follow-fork-mode来决定),另一个进程会被设置为暂停状态。
如果设置了set detach-on-fork off且follow-fork-mode为parent,fork后子进程并不运行,而是处于暂停状态。
看一下log就明白了

注意,最好使用GDB 6.6或以上版本,如果你使用的是GDB6.4,就只有follow-fork-mode模式。

3. attach后多进程调试
    上述方法还是不能同时调试两个进程,假设调试主进程,fork后,子进程已经不知道运行到何处了,所以这就需要让子进程先暂停一下。暂停的方法有很多
    1> 最简单的就是sleep一下
    else if(fpid == 0)  {// child process
          sleep(10); // 给你足够的时间去find子进程id(pstree -ap |  grep a.out),然后attach 
    }
  
    2> 加一段等待代码
    
void debug_wait(char *tag)
{
    while(1)
    {
        if (tag存在) <span style="color:#ff0000;">// tag可以是一个环境变量,也可以是一个文件等</span>
            睡眠一段时间;
        else
            break;
    }
}
   
    3> chromium中
     zygote进程在创建render进程时,正好需要zygote的real PID
  if (pid == 0) {
    // In the child process.
    LOG(ERROR) << "child process(type="<<process_type<<") pid="<<syscall(SYS_gettid);
    write_pipe.reset();

    // Ping the PID oracle socket so the browser can find our PID.
    CHECK(SendZygoteChildPing(pid_oracle.get()));

    // Now read back our real PID from the zygote.
    base::ProcessId real_pid;
    if (!base::ReadFromFD(read_pipe.get(),    <span style="color:#ff0000;">// 等待</span>
                          reinterpret_cast<char*>(&real_pid),
                          sizeof(real_pid))) {
      LOG(FATAL) << "Failed to synchronise with parent zygote process";
    }


参考
http://www.ibm.com/developerworks/cn/linux/l-cn-gdbmp/
————————————————
版权声明:本文为CSDN博主「fingding」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/fingding/article/details/46459095

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值