相信对于初学多进程和多线程的童鞋们,每次编译器报出一大堆看不懂的错误,就头大,这改改,那修修,就是不对。想起来gdb调试,但是不会,一度怀疑是不是gdb不可以进行多进程和多线程的调试,那我告诉你:gdb很强大的,当然可以进行这些调试,即使我一度也这样认为,所以在我懂了一些和查阅了一些资料后,自己写了一些简单的测试用例。整理出来和大家分享。
多进程调试
原文链接:http://blog.163.com/jiams_wang/blog/static/303391492013593502373/
首先,多进程:
parent on 只调试主进程(GDB默认)
child on 只调试子进程
parent off 同时调试两个进程,gdb跟主进程,子进程block在fork位置
child off 同时调试两个进程,gdb跟子进程,主进程block在fork位置
设置:
set follow-fork-mode [parent|child] 就OK了,后面[]里面的选择调试父进程还是子进程。
set detach-on-fork off关闭detach,可以同时调试两个进程,这个跟gdb的版本有关。
info inferiors:查询正在调试的进程
inferior :切换调试的进程
clone-inferior [ -copies n ] [ infno ]:增加n个inferior并且其执行程序指定为和infno号inferior一样;如果不指定n则只增加一个inferior;如果不指定infno,则指定跟当前inferior一样的执行程
remove-inferior infno:删除一个infno号inferior。如果inferior在运行,则不能删除inferior,所以在删除以前需要先kill或者detach这个inferior。
detach inferior infno:detach掉infno号inferior。注意这个inferior仍然存在,可以再次用run等命令执行它,如果想删除结构需要用remove-inferior命令。
kill inferior infno:kill掉infno号inferior。注意这个inferior仍然存在,可以再次用run等命令执行它,如果想删除结构需要用remove-inferior命令。
set print inferior-events on|off
show print inferior-events:这个选项用来打开和关闭inferior状态的提示信息。
set detach-on-fork on|off
show detach-on-fork:这个选项用来控制当fork或者vfork发生的时候,是否detach掉父进程或者子进程(至于具体哪个就由下面的命令决定),默认值是打开,所以想同时调试父进程和子进程的就需要关闭这个选项。
set follow-fork-mode parent|child
show follow-fork-mode:这个选项用来设置当发生fork或者vfork的时候,GDB将继续调试父进程或者子进程,上面的命令也介绍了,如果detach-on-fork选项打开,而不被调试的哪个进程将被detach。
set follow-exec-mode new|same
show follow-exec-mode:当发生exec的时候,如果这个选项是same(默认值),因为父进程已经退出,所以自动在执行exec的inferior上控制子进程。
如果选项是new,则新建一个inferior给执行起来的子进程,而父进程的inferior仍然保留,当前保留的inferior的程序状态是没有执行。
set schedule-multiple on|off
show schedule-multiple:这个选项类似于多线程调试里的set scheduler-locking选项,当选项是off(默认值)的时候,GDB发出执行指令的时候,只有当前inferior会执行。而当选项是on的时候,GDB发出执行命令后,全部状态是执行状态的inferior都会执行。
注意,如果scheduler-locking选项设置为lock的时候,即使schedule-multiple设置为on,也只有当前进程的当前线程会执行。
maint info program-spaces:用来显示当前GDB一共管理了多少地址空间。
多线程调试
原文链接:
http://blog.youkuaiyun.com/kangroger/article/details/47986197
info threads:显示可以调试的所有线程。gdb会为每个线程分配一个ID(和tid不同),编号一般从1开始。后面的ID是指这个ID。
thread ID:切换当前调试的线程为指定ID的线程。
break FileName.cpp:LinuNum thread all:所有线程都在文件FileName.cpp的第LineNum行有断点。
thread apply ID1 ID2 IDN command:多个线程执行gdb命令command。
thread apply all command:所有线程都执行command命令。
set scheduler-locking off|on|step:在调式某一个线程时,其他线程是否执行。off,不锁定任何线程,默认值。on,锁定其他线程,只有当前线程执行。step,在step(单步)时,只有被调试线程运行。
set non-stop on/off:当调式一个线程时,其他线程是否运行。
set pagination on/off:在使用backtrace时,在分页时是否停止。
set target-async on/ff:同步和异步。同步,gdb在输出提示符之前等待程序报告一些线程已经终止的信息。而异步的则是直接返回。
(gdb) info threads
3 Thread 0xb75efb70 (LWP 3551) 0x00110424 in __kernel_vsyscall ()
* 2 Thread 0xb7ff0b70 (LWP 3550) fun1 (val=0x0) at 2.c:17
1 Thread 0xb7ff16c0 (LWP 3547) 0x00110424 in __kernel_vsyscall ()
(gdb) thread 3
[Switching to thread 3 (Thread 0xb75efb70 (LWP 3551))]#0 0x00110424 in __kernel_vsyscall ()
(gdb) n
Single stepping until exit from function __kernel_vsyscall,
which has no line number information.
0x0090d936 in nanosleep () from /lib/libc.so.6
(gdb)
Single stepping until exit from function sleep,
which has no line number information.
fun2 (val=0x0) at 2.c:26
26 }
(gdb)
24 printf("I am %u thread\n",pthread_self());
(gdb)
I am 3076455280 thread
25 sleep(1);
(gdb)
[Switching to Thread 0xb7ff0b70 (LWP 3550)]