<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://www.jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://www.jackxiang.com/post//</link>
<title><![CDATA[[实践OK]Linux 下用gdb单步调试多进程方法，附带学习下调多进程下的epoll片段，也就是用双gdb调试多进程的crack代码，因为代码里有自动拉起的功能，在gdb下用follow-fork-mode=child方式调被拉起bt不了,以及直接gdb后attach子进程。]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[Unix/LinuxC技术]]></category>
<pubDate>Wed, 07 Jan 2015 07:22:38 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	前置：Linux多进程和多线程的一次gdb调试实例:https://typecodes.com/cseries/multilprocessthreadgdb.html ,Linux C/C++开发中gdb进行多进程和多线程的调试一直比较麻烦，在CSDN上看到高科的一篇文章《gdb调试多进程和多线程命令》比较有启发，这里就自己重新整理并做了一个GDB多进程/线程的调试实践。<br/>这个表很重要，两个参数一块用：<br/><textarea name="code" class="php" rows="15" cols="100">
follow-fork-mode&nbsp;&nbsp;detach-on-fork&nbsp;&nbsp;&nbsp;&nbsp;说明
&nbsp;&nbsp;&nbsp;&nbsp;parent&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;on&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GDB默认的调试模式：只调试主进程
&nbsp;&nbsp;&nbsp;&nbsp;child&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; on&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;只调试子进程
&nbsp;&nbsp;&nbsp;&nbsp;parent&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;off&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同时调试两个进程，gdb跟主进程，子进程block在fork位置
&nbsp;&nbsp;&nbsp;&nbsp;child&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; off&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同时调试两个进程，gdb跟子进程，主进程block在fork位置
</textarea><br/><br/>也可将前面的set添加到~/.gdbinit来打开non-stop模式:<br/><textarea name="code" class="php" rows="15" cols="100">
set non-stop on
set follow-fork-mode child
set detach-on-fork off
set pagination off
set target-async 1
set print elements 0
</textarea><br/><br/>查看相关命令：<br/>set follow-fork-mode child<br/>set detach-on-fork off<br/>info inferiors&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#####显示正在调试的进程<br/>inferior 2<br/>show detach-on-fork #Whether gdb will detach the child of a fork is off.<br/>show follow-fork-mode #Debugger response to a program call of fork or vfork is &quot;child&quot;<br/>info b #查看断点<br/>进程树：<br/>pstree -pul<br/>PS查看自己程序名运行的多进程：<br/>ps -f -C multepoolser <br/><br/>break&nbsp;&nbsp;if<br/>要想设置一个条件断点，可以利用break if命令，如下所示：<br/>[cpp] view plain copy<br/>(gdb) break line-or-function if expr&nbsp;&nbsp;<br/>(gdb) break 46 if testsize==100&nbsp;&nbsp;<br/>clean number<br/>清除原文件中某一代码行上的所有断点<br/>注：number 为原文件的某个代码行的行号<br/><br/><br/>断点的管理<br/>1. 显示当前gdb的断点信息: info break<br/>2. delete 删除指定的某个断点: delete breakpoint<br/><br/>单步执行<br/>continue&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;继续运行程序直到下一个断点（类似于VS里的F5）<br/>next&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;逐过程步进，不会进入子函数（类似VS里的F10）&nbsp;&nbsp;#这个不进入函数里。<br/>setp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;逐语句步进，会进入子函数（类似VS里的F11） 的确能进入到函数里面。<br/>until&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 运行至当前语句块结束&nbsp;&nbsp;#没弄明白,试了试没找到规律<br/>finish&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;运行至函数结束并跳出，并打印函数的返回值（类似VS的Shift+F11）<br/>next/n 不进入的单步执行 step 进入的单步执行<br/>finish<br/>如果已经进入了某函数，而想退出该函数返回到它的调用函数中，可使用命令finish<br/>call name<br/>调用和执行一个函数<br/>(gdb) call gen_and_sork( 1234,1,0 )&nbsp;&nbsp;<br/>(gdb) call printf(“abcd”)&nbsp;&nbsp;<br/>$1=4&nbsp;&nbsp;<br/>finish 结束执行当前函数，显示其返回值（如果有的话）<br/><br/>原文件的搜索 search text<br/>该命令可显示在当前文件中包含text串的下一行。<br/>reverse-search text<br/>该命令可以显示包含text 的前一行。<br/><br/>set variable 给变量赋值<br/>signal 将一个信号发送到正在运行的进程<br/>watch 在程序中设置一个监测点（即数据断点）<br/>whatis 显示变量或函数类型<br/><br/>来自GDB调试精粹：http://blog.csdn.net/lwbeyond/article/details/7839225<br/><br/>GDB打印所有字符串：@ http://blog.csdn.net/shuizhizhiyin/article/details/53227913<br/><textarea name="code" class="php" rows="15" cols="100">
(gdb) p header_line
$9 = 0x7fffece71940 &quot;GET / HTTP/1.1&#92;r&#92;nHost: 101.200.228.135:8341&#92;r&#92;nConnection: keep-alive&#92;r&#92;nCache-Control: max-age=0&#92;r&#92;nUpgrade-Insecure-Requests: 1&#92;r&#92;nUser-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gec&quot;...
(gdb) set print elements 0 
(gdb) p header_line&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
$10 = 0x7fffece71940 &quot;GET / HTTP/1.1&#92;r&#92;nHost: 101.200.228.135:8341&#92;r&#92;nConnection: keep-alive&#92;r&#92;nCache-Control: max-age=0&#92;r&#92;nUpgrade-Insecure-Requests: 1&#92;r&#92;nUser-Agent: Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36&#92;r&#92;nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8&#92;r&#92;nAccept-Encoding: gzip, deflate&#92;r&#92;nAccept-Language: zh-CN,zh;q=0.9,en;q=0.8&#92;r&#92;n&#92;r&#92;n&quot;
</textarea><br/>如果出现No symbol &quot;header_line&quot; in current context.，你得切换到那个进程里面去，能切换进去的前提是你提前打了断点：<br/>(gdb) p header_line<br/>No symbol &quot;header_line&quot; in current context.<br/>可：info thread 切换到对应的进程，再打印也就有了。<br/><br/><br/>break FileName.cpp:LinuNum thread all:所有线程都在文件FileName.cpp的第LineNum行有断点。<br/>thread apply ID1 ID2 IDN command:多个线程执行gdb命令command。<br/>thread apply all command：所有线程都执行command命令。<br/>set scheduler-locking off&#124;on&#124;step：在调式某一个线程时，其他线程是否执行。off，不锁定任何线程，默认值。on，锁定其他线程，只有当前线程执行。step，在step（单步）时，只有被调试线程运行。<br/>set non-stop on/off:当调式一个线程时，其他线程是否运行。<br/>set pagination on/off:在使用backtrace时，在分页时是否停止。<br/>set target-async on/ff:同步和异步。同步，gdb在输出提示符之前等待程序报告一些线程已经终止的信息。而异步的则是直接返回。<br/>来自：http://blog.csdn.net/helloktt/article/details/73252943<br/>http://www.tolxs.com/?p=302<br/>(gdb)&nbsp;&nbsp;show detach-on-fork<br/>Whether gdb will detach the child of a fork is off.<br/>(gdb) show follow-fork-mode<br/>Debugger response to a program call of fork or vfork is &quot;child&quot;<br/><br/>出现：<br/>(gdb) n<br/>Cannot execute this command while the selected thread is running.<br/><br/>(gdb) info threads<br/>&nbsp;&nbsp;Id&nbsp;&nbsp; Target Id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Frame <br/>&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;Thread 0x7fffece72700 (LWP 27660) &quot;multepoolser&quot; handleEpollRdMessage (threadNum=0) at multepoolser.c:262<br/>* 2&nbsp;&nbsp;&nbsp;&nbsp;Thread 0x7ffff7fde840 (LWP 21243) &quot;multepoolser&quot; (running)<br/>&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;Thread 0x7ffff7fde840 (LWP 21239) &quot;multepoolser&quot; 0x00007ffff668774c in fork () from /lib64/libc.so.6<br/><br/>root&nbsp;&nbsp;&nbsp;&nbsp; 21239 16286&nbsp;&nbsp;0 17:22 pts/1&nbsp;&nbsp;&nbsp;&nbsp;00:00:00 [httpmut: master process] master process<br/>apache&nbsp;&nbsp; 21243 21239&nbsp;&nbsp;0 17:22 pts/1&nbsp;&nbsp;&nbsp;&nbsp;00:00:00 [httpmut: worker process] worker process<br/><br/>目前在进程：2，前面有*号，我得到3上面去，怎么弄？<br/>thread 3<br/>(gdb) thread 3<br/>[Switching to thread 3 (Thread 0x7fffece72700 (LWP 27660))]<br/>#0&nbsp;&nbsp;handleEpollRdMessage (threadNum=0) at multepoolser.c:262<br/>262&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf(&quot;handleEpollRdMessage function &#039;s threadNum=%d&#92;n&quot;,threadNum);<br/>(gdb) n<br/>handleEpollRdMessage function &#039;s threadNum=0<br/>263&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int recvlen=-1,epollRdQueRet=-1;//返回<br/>info threads #此时就在3了吧<br/>(gdb) info threads<br/>&nbsp;&nbsp;Id&nbsp;&nbsp; Target Id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Frame <br/>* 3&nbsp;&nbsp;&nbsp;&nbsp;Thread 0x7fffece72700 (LWP 27660) &quot;multepoolser&quot; handleEpollRdMessage (threadNum=0) at multepoolser.c:263<br/>&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;Thread 0x7ffff7fde840 (LWP 21243) &quot;multepoolser&quot; (running)<br/>&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;Thread 0x7ffff7fde840 (LWP 21239) &quot;multepoolser&quot; 0x00007ffff668774c in fork () from /lib64/libc.so.6<br/><br/>卡这儿了，也就是主进程网络那边没有来Epoll句柄，getepollRdFromQue队列一直是空的，怎么办？<br/>(gdb) p epollRdQueRet<br/>$2 = -1<br/>(gdb) n<br/>455&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/>(gdb) <br/>302&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; epollRdQueRet = getepollRdFromQue(&amp;sockRdQue[threadNum],&amp;epollRd);//只要有生产的fd进来并该线程获取到了，就立即去epoll读队列里抢,一线程一队列，不用锁。<br/>(gdb) <br/>303&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(epollRdQueRet == -1) continue;//没有获取到epollRd，继续获取。<br/>(gdb) <br/>455&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125;<br/><br/>此时如果有的进程需要运行，怎么办？GDB命令：thread apply 3 1 continue #让线程3继续运行,注意我顾意把主线程1也continue。<br/>thread apply 3 1 2 continue<br/><br/><br/>需要实践，链接如下：<br/>http://blog.sina.com.cn/s/blog_53fab15a0101g88r.html<br/>https://www.cnblogs.com/frankbadpot/archive/2010/06/23/1762916.html<br/>http://blog.csdn.net/wangyin159/article/details/47169267<br/><br/>=============================================================================<br/><br/>背景：当你在做一些多进程调试时，会出现一个问题，那就是子进程往往不太好调试，怎么办？如果子进程一直在while里飞快的运行着怎么办，这篇文章就是教会你进行双gdb调试，以实现了子进程的调试，这儿在没有调试时，其子进程是不断的打印，当然最好在while里加一个sleep，但第二个gdb进入后则会存在第一个gdb的打印变慢了，此时，可以在第二个gdb里打印相关变量，达到对子进程的调试目的，特别注意的是，第二个gdb一定要在那个子进程的行里break（这儿是31行）进行调试，而不是放在其它地方，否则是没法调试到子进程的。第三个是：进程中断点.然后用c(这里要用continue,因为attach的进程已经在运行了,不能用run)。最后，子进程死了父亲进程拉起，crack这块可能是return退出了，自己打印是crack，导致并不是真正的crack了，也就不是coredump了，特别注意这个问题。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 当你在程序中使用fork(),如果用gdb来调试.不管是你在子进程是否设置断点.你都只能在父进程单步调试,而没办法进入到子进程当中进行单步调试.因为gdb的所有处理(查看堆栈,内存,变量值)都是针对当前进程空间.<br/><br/>那么是否就没办法调试多进程程序的子进程代码呢?办法还是有的,一般的标准方法是再打开一个gdb用attach功能来调试子进程gdb attach 功能是不执行被调试程序，而是把gdb“挂”到一个已经运行的进程之上来进行调试，这挂载的动作称为attach.当然也包括挂载子进程。<br/><br/>注意两点：<br/>0.当主gdb进来后进行断点后，子进程尽管断点了，但依然运行（为第二个gdb作暂停准备之用），而当第二个gdb对子进程进行attach后，其主gdb的子进程的打印动作也就暂停（为方便调试，可以在进程启动后，设定sleep一段时间，如30s，其实只要第二个gdb一attach到子进程，子进程就柱塞了。），此时子gdb再进行设置断点，按c运行，按n作next就行。<br/>1.子进程的主gdb点和第二个gdb的break点要同一行？不必要，其主gdb只是起到在第二个gdb单独调该进程时起到暂停其主的子进程的作用罢了。<br/>2.在子进程的gdb里，要用c来继续，(这里要用continue,因为attach的进程已经在运行了,不能用run！（也就是：主进程用r（先运行着，主进程不退出。），子进程用c，继续在原来那个停下来的点继续运行到后，再用n命令，即next一步一步查问题，n（next）：显示的是即将运行这一行，也就是还没有运行。）<br/>3.gdb调试epoll时遇到的Interrupted system call:<br/>signal(SIGALRM,timer_handle);<br/>最近写了个多线程数据处理的程序,其中用到sem_wait()在信号量为0的时候挂起程序. 程序全速执行的时候没有任何问题,但gdb单步调试的时候,因执行sem_wait()函数而挂起的线程经常出现Interrupted system call,不能正常执行.<br/>&nbsp;&nbsp;&nbsp;&nbsp;原因在于,gdb单步调试的时候会在断点处插入一条中断指令,当程序执行到该断点处的时候会发送一个SIGTRAP信号,程序转去执行中断相应,进而gdb让程序停下来进行调试. 对于sem_wait&#92;wait&#92;read等会阻塞的函数在调试时,如果阻塞,都可能会收到调试器发送的信号,而返回非0值.<br/>&nbsp;&nbsp;&nbsp;&nbsp;为了解决这个问题需要在代码中忽略由于接收调试信号而产生的&quot;错误&quot;返回:<br/><textarea name="code" class="C" rows="15" cols="100">
&nbsp;&nbsp;&nbsp;&nbsp;while(sem_wait(&amp;sem) != 0) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(errno!=EINTR) &#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return -1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#125;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
</textarea><br/><br/>到一篇文章《gdb常用命令及使用gdb调试多进程多线程程序》：http://www.cnblogs.com/33debug/p/7043437.html ，代码编译无法通过，代码调整如下,gdb_pthread.c：<br/><textarea name="code" class="php" rows="15" cols="100">
#include &lt;stdio.h&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
#include &lt;pthread.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;unistd.h&gt;

int main(int argc, const char **argv)
&#123;
&nbsp;&nbsp;&nbsp;&nbsp;int pid;
&nbsp;&nbsp;&nbsp;&nbsp;pid = fork();
&nbsp;&nbsp;&nbsp;&nbsp;if (pid != 0)&nbsp;&nbsp;&nbsp;&nbsp;//add the first breakpoint.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Parent();
&nbsp;&nbsp;&nbsp;&nbsp;else
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Child();
&nbsp;&nbsp;&nbsp;&nbsp;return 0;
&#125;

//Parent process handle after generate a thread.
void * ParentDo(char *argv)
&#123;
&nbsp;&nbsp;&nbsp;&nbsp;pid_t pid = getpid();
&nbsp;&nbsp;&nbsp;&nbsp;pthread_t tid = pthread_self();&nbsp;&nbsp; //Get the thread-id selfly.
&nbsp;&nbsp;&nbsp;&nbsp;char tprefix[] = &quot;thread&quot;;

&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;[%s]: [%d] [%s] [%lu] [%s]&#92;n&quot;, argv, pid, tprefix, tid, &quot;step2&quot;);&nbsp;&nbsp;//add the second breakpoint.
&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;[%s]: [%d] [%s] [%lu] [%s]&#92;n&quot;, argv, pid, tprefix, tid, &quot;step3&quot;);

&nbsp;&nbsp;&nbsp;&nbsp;return NULL;
&#125;


//Parent process handle.
void Parent()
&#123;
&nbsp;&nbsp;&nbsp;&nbsp;pid_t pid = getpid();
&nbsp;&nbsp;&nbsp;&nbsp;char cParent[] = &quot;Parent&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;char cThread[] = &quot;Thread&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;pthread_t pt;

&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;[%s]: [%d] [%s]&#92;n&quot;, cParent, pid, &quot;step1&quot;);

&nbsp;&nbsp;&nbsp;&nbsp;if (pthread_create(&amp;pt, NULL, (void *)*ParentDo, cThread))
&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;[%s]: Can not create a thread.&#92;n&quot;, cParent);
&nbsp;&nbsp;&nbsp;&nbsp;&#125;

&nbsp;&nbsp;&nbsp;&nbsp;ParentDo(cParent);
&nbsp;&nbsp;&nbsp;&nbsp;sleep(1);
&#125;

//Child process handle.
void Child()
&#123;
&nbsp;&nbsp;&nbsp;&nbsp;pid_t pid = getpid();
&nbsp;&nbsp;&nbsp;&nbsp;char prefix[] = &quot;Child&quot;;
&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;[%s]: [%d] [%s]&#92;n&quot;, prefix, pid, &quot;step1&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;return;
&#125; 
</textarea><br/><br/><br/>关于GDB无法调试epoll的疑问？<br/>这种交互式的网络程序最好不用gdb来调？<br/>调试网络通讯程序最好别用GDB，epoll你可以用strace，gdb是用来调试 C数据结构逻辑之类的。<br/>打日志是我的首选调试方法，如果程序崩溃就看core 文件，如果死锁就 attach上去，其他的错误我从不用GDB<br/>不是epoll和gdb的问题，而是在gdb下epoll_wait 信号处理和正常运行有差异造成的，应该是这个。<br/>摘自：http://bbs.chinaunix.net/thread-1551201-1-1.html<br/><br/>多进程调试如下所述即可，如下，特别是新的linux内核版本能支持到多进程了，相当好用：<br/>在2.5.60版Linux内核及以后，GDB对使用fork/vfork创建子进程的程序提供了follow-fork-mode选项来支持多进程调试。<br/>follow-fork-mode的用法为：<br/>set follow-fork-mode [parent&#124;child]<br/>parent: fork之后继续调试父进程，子进程不受影响。 <br/>child: fork之后调试子进程，父进程不受影响。 <br/>因此如果需要调试子进程，在启动gdb后：<br/>(gdb) set follow-fork-mode child<br/><br/>这块可以研究一下，新的内核及新的gdb有新功能很方便使用：<br/>set follow-fork-mode child<br/>//set detach-on-fork on //gdb控制父子进程，不让调试了： Can&#039;t attach LWP 24731: Operation not permitted，得打开：ON。<br/>b 146 //main里的子进程行<br/>b 192&nbsp;&nbsp;//子进程调用的函数原型行<br/>r //执行到子进程断点处<br/>n //子进程单步执行<br/><br/>实践心得：一般情况下多线程的时候,由于是同时运行的,最好设置 set scheduler-locking on 这样的话,只调试当前线程 。<br/>off 不锁定任何线程，也就是所有线程都执行，这是默认值。 on 只有当前被调试程序会执行。 <br/>vi bp.list <br/><textarea name="code" class="php" rows="15" cols="100">
set follow-fork-mode child
set scheduler-locking on&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
+++++++++++++gdb scheduler-locking+++++++++++++++++
http://blog.csdn.net/wocjj/article/details/7603092
https://jackxiang.com/post/8099/
+++++++++++++++++++++++++++++++++++++++
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
#b putUpFilePart2Que 
b saveAndCobinFileSlice
</textarea><br/>gdb.sh<br/><textarea name="code" class="php" rows="15" cols="100">
ulimit -c unlimited
gdb multepoolser -x bp.list 
</textarea><br/>（一）这块在调试epoll时，在n单步执行卡后（c执行前先断点），得通过浏览器模拟socket请求才能过得去，否则会一直卡那儿，如下：<br/><textarea name="code" class="php" rows="15" cols="100">
214&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(-1==(wait_fds=epoll_wait(epfd,events,MAX_EVENTS,-1)))&#123; // 等待epoll事件的发生 
(gdb) n //一直卡在这儿，等待web端请求

224&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for( int i=0; i&lt;wait_fds &amp;&amp; g_bRun; ++i ) // for循环中可以修改为线程池处理epoll事件 （web请求后自动执行到224行了，由214跳转到224行，也就是epoll找到一个状态改变的，于是跑这儿了，于是可继续跟踪下去，此时web一直等待，如果一时不返回会出现浏览器超时。）
(gdb) 
226&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( events[i].data.fd == listenFd &amp;&amp; cur_fds&lt;MAX_EVENTS)&#123;
(gdb) 

继续n单步执行，调试参数：
(gdb) n
227&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int sockfd = accept( listenFd, (sockaddr *)&amp;clientaddr, &amp;clilen );
(gdb) print sockfd
$2 = 0
(gdb) n
228&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if( sockfd &lt; 0 )&#123;
(gdb) print sockfd
$3 = 8
</textarea><br/><br/>这块如果continue后，中间因为断点就一次是没法下次进入的，需要引入gdb判断（if &#123;expression&#125; else end条件判断语句, if 后面所带的表达式为一般的GDB表达式：http://blog.csdn.net/horkychen/article/details/9372039）及观察点，才能更加深入了解，下面是试图没有断点运行起来后实现ctrl+C退出，想继续n的尝试：<br/>（二）再就是对c后一直卡那儿，可以按ctrl+C退出（ SIGINT&nbsp;&nbsp; ：来自键盘的中断信号 ( ctrl + c ) .），SIGTERM：kill 命令发出 的信号.，继续n执行：<br/>Program received signal SIGINT, Interrupt.<br/>0x0000003c9a2d3fd3 in __epoll_wait_nocancel () from /lib64/libc.so.6<br/>(gdb) n<br/>Single stepping until exit from function __epoll_wait_nocancel, <br/>which has no line number information.<br/><br/>这块不知怎么回事....需要进一步学习了解。<br/><br/>Process(listenFd); //运行至工作子进程的函数,;b 192进行单步执行。<br/><br/>直接gdb后attach子进程：<br/>#ps -f -C multepoolser<br/>UID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PID&nbsp;&nbsp;PPID&nbsp;&nbsp;C STIME TTY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TIME CMD<br/>root&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2150 19720&nbsp;&nbsp;0 17:09 pts/1&nbsp;&nbsp;&nbsp;&nbsp;00:00:00 [httpmut: master process] master process<br/>apache&nbsp;&nbsp;&nbsp;&nbsp;2151&nbsp;&nbsp;2150 93 17:09 pts/1&nbsp;&nbsp;&nbsp;&nbsp;00:00:01 [httpmut: worker process] worker process<br/>2151就是子进程，怎么办？<br/>gdb&nbsp;&nbsp; #运行gdb<br/>attach 2151<br/>现在就可以调试了。一个新的问题是，子进程一直在运行，attach上去后都不知道运行到哪里了。有没有办法解决呢？<br/><br/>一个办法是，在要调试的子进程初始代码中，比如main函数开始处，加入一段特殊代码，使子进程在某个条件成立时便循环睡眠等待，attach到进程后在该代码段后设上断点，再把成立的条件取消，使代码可以继续执行下去。<br/><br/>至于这段代码所采用的条件，看你的偏好了。比如我们可以检查一个指定的环境变量的值，或者检查一个特定的文件存不存在。以文件为例，其形式可以如下：<br/><br/>1<br/>2<br/>3<br/>4<br/>5<br/>6<br/>7<br/>8<br/>9<br/>10<br/>void debug_wait(char *tag_file)<br/>&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;while(1)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (tag_file存在)<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;睡眠一段时间;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>&#125;<br/>当attach到进程后，在该段代码之后设上断点，再把该文件删除就OK了。当然你也可以采用其他的条件或形式，只要这个条件可以设置/检测即可。<br/><br/>Attach进程方法还是很方便的，它能够应付各种各样复杂的进程系统，比如孙子/曾孙进程，比如守护进程（daemon process），唯一需要的就是加入一小段代码。<br/><br/>https://www.ibm.com/developerworks/cn/linux/l-cn-gdbmp/<br/><br/>学习参考：<br/>http://blog.csdn.net/nyist327/article/details/40040011<br/>http://blog.sina.cn/dpool/blog/s/blog_55d572ca0100v8e8.html<br/><br/>修改如下：<br/><textarea name="code" class="C" rows="15" cols="100">
while (g_bRun)
&#123;
&nbsp;&nbsp;&nbsp;&nbsp;if(-1==(wait_fds=epoll_wait(epfd,events,MAX_EVENTS,-1)))&#123; // 等待epoll事件的发生 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(errno!=EINTR)//gdb 调式时的出现：Interrupted system call，临时性屏蔽该退出信号。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//return -1;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//perror(&quot;epoll_wait&quot;);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//exit(EXIT_FAILURE);
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;// 处理所发生的所有事件
&nbsp;&nbsp;&nbsp;&nbsp;for( int i=0; i&lt;wait_fds &amp;&amp; g_bRun; ++i ) // for循环中可以修改为线程池处理epoll事件
&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if( events[i].data.fd == listenFd &amp;&amp; cur_fds&lt;MAX_EVENTS)&#123;
</textarea><br/><br/>主gdb：<br/>(gdb) b 167<br/>Breakpoint 1 at 0x4025a1: file multipepollserver.cpp, line 167.<br/>(gdb) b 147<br/>Breakpoint 2 at 0x40250f: file multipepollserver.cpp, line 147.<br/>(gdb) r<br/>Starting program: /home/xiangdong/multepoolserver/multipepollserver <br/>[Thread debugging using libthread_db enabled]<br/>Detaching after fork from child process 27539.<br/>[New Thread 0x2afb66031230 (LWP 27536)]<br/><br/>Breakpoint 1, main (argc=1, argv=0x7fff550003c8, envp=0x7fff550003d8) at multipepollserver.cpp:168<br/>168&nbsp;&nbsp;&nbsp;&nbsp;<br/><br/>辅助gdb：<br/>(gdb) b 147<br/>Breakpoint 1 at 0x40250f: file multipepollserver.cpp, line 147.<br/>(gdb) c<br/>Continuing.<br/>n<br/><br/>以上代码来自，也就是上面的程序调试的整个代码放在：http://jackxiang.com/post/6937/&nbsp;&nbsp;，不完善进一步学习中。<br/><br/>来自：<br/>&nbsp;&nbsp;&nbsp;&nbsp;http://blog.sina.com.cn/s/blog_5cec1e1d0100guwf.html<br/>&nbsp;&nbsp;&nbsp;&nbsp;http://blog.csdn.net/qiaoliang328/article/details/7404032<br/>&nbsp;&nbsp;&nbsp;&nbsp;http://bbs.csdn.net/topics/380004392<br/>首先我们看一个如下简单的多进程程序。<br/><br/><textarea name="code" class="C" rows="15" cols="100">
/*
Author: jackxiang xdy***@126.com
debug multi-process by gdb.
*/
#include &lt;sys/types.h&gt;
#include &lt;unistd.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

#define PRINT_INT(e) printf(&quot;%s=%d&#92;n&quot;,#e,e)

int main()
&#123;
&nbsp;&nbsp;&nbsp;&nbsp;pid_t pid;
&nbsp;&nbsp;&nbsp;&nbsp;int i,val = 100;

&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;process id %d&#92;n&quot;,getpid());

&nbsp;&nbsp;&nbsp;&nbsp;pid = fork();
&nbsp;&nbsp;&nbsp;&nbsp;PRINT_INT(val);

&nbsp;&nbsp;&nbsp;&nbsp;if(pid == 0)
&nbsp;&nbsp;&nbsp;&nbsp;&#123;/* child process */
&nbsp;&nbsp;&nbsp;&nbsp;val+=100;
&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;child process id %d,parent id %d&#92;n&quot;,getpid(),getppid());

&nbsp;&nbsp;&nbsp;&nbsp;PRINT_INT(val);
&nbsp;&nbsp;&nbsp;&nbsp;i = 0;
&nbsp;&nbsp;&nbsp;&nbsp;while(1)
&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;child [%d]&#92;n&quot;,i++); //31行：这是文章中所说的子进程的31行，在这儿也设置一个断点，让子进程在这儿停下来供另一个gdb调试。这一行是双gdb的第二个的值，根据描述它必须在31行供gdb调试。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(1);
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;else if(pid &gt;0)
&nbsp;&nbsp;&nbsp;&nbsp;&#123;/* parent child */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;parent process id %d&#92;n&quot;,getpid()); 

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(i=0 ; i &lt; 5 ; i++)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //这儿是39行
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;parent [%d]&#92;n&quot;,i);&nbsp;&nbsp;//这是文章中的第41行，这儿设置父进程断点位置。
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;val+=10;

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PRINT_INT(val);

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wait(NULL);
&nbsp;&nbsp;&nbsp;&nbsp;&#125;
&nbsp;&nbsp;&nbsp;&nbsp;else /* error */
&nbsp;&nbsp;&nbsp;&nbsp;&#123;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(-1);
&nbsp;&nbsp;&nbsp;&nbsp;&#125;

&nbsp;&nbsp;&nbsp;&nbsp;PRINT_INT(val);
&nbsp;&nbsp;&nbsp;&nbsp;return 0;
&#125;
</textarea><br/><br/>这个程序很简单,就是子进程在无限循环打印屏幕,而父进程在用wait等待.<br/><br/>编译 gcc test_fork.c -o test_fork -g<br/><br/>1.双gdb调试<br/><br/>首先用常规方法gdb test_fork.c 调试程序,分别在31行,41行设断点,然后用run执行程序,可以看到gdb在41行父进程的断点停下来.但是子进程在自行执行,无法在31断点停下.<br/><br/>[root@localhost src]# gdb test_fork<br/>GNU gdb Fedora (6.8-27.el5)<br/>(gdb) b 31<br/>Breakpoint 1 at 0x8048541: file test_fork.c, line 31.<br/>(gdb) b 41<br/>Breakpoint 2 at 0x804858e: file test_fork.c, line 41.<br/>(gdb) r<br/>Starting program: /home/hxy/src/test_fork<br/>process id 3959<br/>Detaching after fork from child process 3962.<br/>val=100<br/>parent process id 3959<br/><br/>Breakpoint 2, main () at test_fork.c:41<br/>41 printf(&quot;parent [%d]&#92;n&quot;,i);<br/>(gdb) val=100<br/>child process id 3962,parent id 3959<br/>val=200<br/>child [0]<br/>child [1]<br/>child [2]<br/>child [3]<br/>child [4]<br/>child [5]<br/>child [6]<br/>child [7]<br/>nchild [8]<br/>child [9]<br/><br/>parent [0]<br/>39 for(i=0 ; i &lt; 5 ; i++)<br/>(gdb) child [10]<br/>n<br/><br/><br/>这时用gdb attach功能来调试子进程,首先用 ps -aux &#124; grep test_fork找出子进程号.<br/><br/>然后用 gdb test_fork &lt;进程号&gt;挂入已经知进程.这时就可以看到在子进程的断点可以停下来,而且父进程的gdb窗口里,子进程输出停下并受子进程的gdb控制,这里你可以用常规调试手段来看程序了.(如看memory,watch,stack等)<br/><br/>操作步骤,进入gdb首先用b 31 设置子进程中断点.然后用c(这里要用continue,因为attach的进程已经在运行了,不能用run)<br/><br/>然后可以看到断点在生效了.至此可以常规调试方法即可<br/><br/>[root@localhost src]# ps -aux &#124; grep test_fork<br/>Warning: bad syntax, perhaps a bogus &#039;-&#039;? See /usr/share/doc/procps-3.2.7/FAQ<br/>root 3957 0.0 0.2 11012 4824 pts/7 S+ 13:18 0:00 gdb test_fork<br/>root 3959 0.0 0.0 1516 328 pts/7 T 13:19 0:00 /home/hxy/src/test_fork<br/>root 3962 0.0 0.0 1516 280 pts/7 S 13:19 0:00 /home/hxy/src/test_fork<br/>root 3985 0.0 0.0 5020 672 pts/9 R+ 13:19 0:00 grep test_fork<br/>[root@localhost src]# gdb test_fork 3962<br/>GNU gdb Fedora (6.8-27.el5)<br/>Copyright (C) 2008 Free Software Foundation, Inc.<br/>(gdb) b 31<br/>Breakpoint 1 at 0x8048541: file test_fork.c, line 31.<br/>(gdb) c<br/>Continuing.<br/><br/>Breakpoint 1, main () at test_fork.c:31<br/>31 printf(&quot;child [%d]&#92;n&quot;,i++);<br/>(gdb) n<br/>32 sleep(1);<br/>(gdb) n<br/>33 &#125;<br/>(gdb)<br/><br/>2.图形界面kdbg的调试<br/><br/>命令行界面gdb还是太麻烦了,一般我们还是采用界面前端来进行调试程序,一般用KDE自带KDbg最为方便.<br/><br/>2.1 首先用一个Kdbg打开程序<br/><br/>在图形界面设置断点,然后运行,可以看到主程序的断点已经进入并停下来了.<br/>Linux 下用gdb单步调试多进程方法. - youdianluan - youdianluan的博客<br/><br/>2.2 再打开一个kdbg,并且打开test_fork,设置好子进程的断点,选择主菜单的Execution-&gt;Attach,这时会出现如下界面,从进程列表选择子进程或用ps查到子进程ID直接输入即可<br/>Linux 下用gdb单步调试多进程方法. - youdianluan - youdianluan的博客<br/>2.3 此时两个kdbg在同时调一个程序不同进程,注意所有标准输入输出都发生在调试主进程的kdbg的终端窗口里<br/>Linux 下用gdb单步调试多进程方法. - youdianluan - youdianluan的博客<br/> <br/>转自：http://blog.csdn.net/youdianluanluan/article/details/7006995<br/><br/><br/>最后，查看断点，清除掉断点后，可继续c一下，第一个的gdb就又开始运行起来了：<br/>(gdb) info break<br/>Num Type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Disp Enb Address&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;What<br/>2&nbsp;&nbsp; breakpoint&nbsp;&nbsp;&nbsp;&nbsp; keep y&nbsp;&nbsp; 0x00000000004006d4 in main at test_fork.c:35<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l<br/>33&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(1)<br/>34&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#123;<br/>35&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf(&quot;child [%d]&#92;n&quot;,i++);<br/>36&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(1);<br/>37&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/>38&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;<br/><br/>(gdb) c<br/><br/>每次想要对子进程的断点清掉后，都得重新：gdb test_fork 3962 才行。<br/>c ： 是用来一直运行到断点。<br/>n： 单步过行，一步步运行，当指向某行时它并没有运行，而是n后才会运行。
]]>
</description>
</item><item>
<link>http://www.jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论] [实践OK]Linux 下用gdb单步调试多进程方法，附带学习下调多进程下的epoll片段，也就是用双gdb调试多进程的crack代码，因为代码里有自动拉起的功能，在gdb下用follow-fork-mode=child方式调被拉起bt不了,以及直接gdb后attach子进程。]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://www.jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>