日期:2014-05-16  浏览次数:20485 次

gdb多线程/多进程(守护进程)调试



一 调试多进程
1) follow-fork-mode :


set follow-fork-mode [parent|child]

parent: fork之后继续调试父进程,子进程不受影响。
child: fork之后调试子进程,父进程不受影响。


在使用如下方法设置完要调试的程序后:



gdb命令行的 –-args 参数
gdb环境中 set args命令。
gdb --pid=PID(ps -ef | grep your_prog)


如果需要调试子进程,在启动gdb后:



(gdb) set follow-fork-mode child


并在子进程代码设置断点。

此外还有detach-on-fork参数,指示GDB在fork之后是否断开(detach)某个进程的调试,或者都交由GDB控制:

set detach-on-fork [on|off]

on: 断开调试follow-fork-mode指定的进程。
off: gdb将控制父进程和子进程。follow-fork-mode指定的进程将被调试,另一个进程置于暂停(suspended)状态。
由于follow-fork-mode的调试必然是从父进程开始的,对于fork多次,调试起来并不方便。

2) attach调试:
GDB有附着(attach)到正在运行的进程的功能,即attach <pid>命令。因此可以利用该命令attach到子进程然后进行调试。通过ps和pstree可以查看到所要调试的子进程pid。

问题是,子进程一直在运行,attach上去后都不知道运行到哪里了。一个办法是,在要调试的子进程初始代码中,加入一段特殊代码,使子进程在某个条件成立时便循环睡眠等待,attach到进程后在该代码段后设上断点,再把成立的条件取消,使代码可以继续执行下去。

Attach进程方法还是很方便的,它能够应付各种各样复杂的进程系统,比如孙子/曾孙进程,比如守护进程(daemon process),唯一需要的就是加入一小段代码。适合于各种复杂情况,特别是守护进程。

3) gdb wrapper:
专用于fork+exec模式,不用添加额外代码,但需要X环境支持(xterm/VNC)。

可参考:http://www.ibm.com/developerworks/cn/linux/l-cn-gdbmp/index.html

二 调试多进程
GDB多线程调试的基本命令:

info threads 查看当前进程的线程。
thread <ID> 切换调试的线程为指定ID的线程。
break [LOCATION] [thread THREADNUM] [if CONDITION]  在[LOCATION]处为[thread THREADNUM]设置断点在满足条件[if CONDITION]时停住 。
thread apply ID1 ID2 command 让一个或者多个线程执行GDB命令command。
thread apply all command  让所有被调试线程执行GDB命令command。
set scheduler-locking off|on|step,这个是问得最多的。在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,怎么只让被调试程序执行呢?通过这个命令就可以实现这个需求。
off 不锁定任何线程,也就是所有线程都执行,这是默认值。
on 只有当前被调试程序会执行。
step 在单步的时候,除了next过一个函数的情况(熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)以外,只有当前线程会执行。
other:
gdb中的变量以$开头,比如你想打印一个数组中的个个元素,你可以这样:


(gdb) set $i = 0
(gdb) p a[$i++]

调试宏:在GCC编译程序的时候,加上-ggdb3参数,就可以了
info macro – 你可以查看这个宏在哪些文件里被引用了,以及宏定义是什么样的。
macro – 你可以查看宏展开的样子。
x命令是用来查看内存的,在gdb中 “help x” 你可以查看其帮助。
x/x 以十六进制输出
x/d 以十进制输出
x/c 以单字符输出
x/i  反汇编 – 通常,我们会使用 x/10i $ip-20 来查看当前的汇编($ip是指令寄存器)
x/s 以字符串输出
command命令,其就是把一组gdb的命令打包,有点像字处理软件的“宏”。
(gdb) command 1
Type commands for when breakpoint 1 is hit, one per line.
End with a line saying just "end".
>print arg1
>print arg2
>print arg3
>end
(gdb)
参考:
http://www.ibm.com/developerworks/cn/linux/l-cn-gdbmp/index.html

http://coolshell.cn/articles/3643.html