常常我们会碰到在多进程程序中,利用GDB无法调试子进程问题。实际上,GDB 没有对多进程程序调试提供直接支持。例如,使用GDB调试某个进程,如果该进程fork了子进程,GDB会继续调试该进程,子进程会不受干扰地运行下去。如果你事先在子进程代码里设定了断点,子进程会收到SIGTRAP信号并终止。那么该如何调试子进程呢?其实我们可以利用GDB的特点或者其他一些辅助手段来达到目的。此外,GDB 也在较新内核上加入一些多进程调试支持。
-
#include <stdio.h>
-
#include <unistd.h>
-
-
int main()
-
...{
-
if(fork() == 0)
-
...{
-
printf("Child Process say hello to you! ");
-
sleep(5);
-
exit(0);
-
}
-
else
-
printf("Parent Process, Hello ");
-
-
return 0;
-
}
方法一:
ubuntu默认情况下你在gdb中使用attach id是权限不够的,所以你需要:sudo chmod +s /usr/bin/gdb
-
在父子进程中加一句while(pause) sleep(1);,让其暂停,然后后台运行程序,通过ps获取子进程的PID。(如下所示,ps显示的./fork有两个,orisun是进程的有效用户,第一个数字是进程ID,第二个数字是其父进程ID)
-
运行gdb,attach 子进程ID
-
orisun@zcypc:~$ ./fork &
-
[1] 13294
-
orisun@zcypc:~$ ps -ef|grep fork
-
790 1 0 09:00 ? 00:00:01 dbus-daemon --system --fork --activation=upstart
-
orisun 1546 1 0 09:00 ? 00:00:03 //bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session
-
orisun 12584 1 0 20:23 ? 00:00:12 gedit /home/orisun/fork.c
-
orisun 13294 13239 0 20:53 pts/0 00:00:00 ./fork
-
orisun 13295 13294 0 20:53 pts/0 00:00:00 ./fork
-
orisun 13297 13239 0 20:54 pts/0 00:00:00 grep --color=auto fork
-
orisun@zcypc:~$ gdb
-
GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
-
Copyright (C) 2010 Free Software Foundation, Inc.
-
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
-
This is free software: you are free to change and redistribute it.
-
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
-
and "show warranty" for details.
-
This GDB was configured as "i686-linux-gnu".
-
For bug reporting instructions, please see:
-
<http://www.gnu.org/software/gdb/bugs/>.
-
(gdb) attach 13295
-
Attaching to process 13295
-
Reading symbols from /home/orisun/fork...done.
-
Reading symbols from /lib/i386-linux-gnu/libc.so.6...Reading symbols from /usr/lib/debug/lib/i386-linux-gnu/libc-2.13.so...done.
-
done.
-
Loaded symbols for /lib/i386-linux-gnu/libc.so.6
-
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
-
Loaded symbols for /lib/ld-linux.so.2
-
0x00bd8416 in __kernel_vsyscall ()
-
(gdb) backtrace
-
#0 0x00bd8416 in __kernel_vsyscall ()
-
#1 0x0049bfc0 in __nanosleep_nocancel ()
-
at ../sysdeps/unix/syscall-template.S:82
-
#2 0x0049bde2 in __sleep (seconds=<value optimized out>)
-
at ../sysdeps/unix/sysv/linux/sleep.c:138
-
#3 0x08048595 in main () at fork.c:25
-
(gdb) up 3
-
#3 0x08048595 in main () at fork.c:25
-
while(pause) sleep(1);
-
(gdb) list
-
if((pid=fork())<0){
-
perror("fork");
-
exit(1);
-
}
-
if(pid==0){
-
while(pause) sleep(1);
-
if((arr=shmat(shmid,NULL,0))==(void*)-1){ //子进程中把共享内存映射到本,进行修改
-
perror("shmat");
-
exit(1);
-
}
-
(gdb) break 31
-
Breakpoint 1 at 0x8048600: file fork.c, line 31.
-
(gdb) set pause=0
-
(gdb) continue
-
Continuing.
-
-
Breakpoint 1, main () at fork.c:31
-
if(shmdt(arr)==-1){
-
(gdb) p arr
-
$1 = 0xb77fb000 "abc"
-
(gdb)
方法二:follow-fork-mode
不需要专门加while(pause) sleep(1);这种代码了。
follow-fork-mode的用法为:
set follow-fork-mode [parent|child]
* parent: fork之后继续调试父进程,子进程不受影响。
* child: fork之后调试子进程,父进程不受影响。
因此如果需要调试子进程,在启动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)状态。
-
orisun@zcypc:~$ gdb ./fork
-
GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
-
Copyright (C) 2010 Free Software Foundation, Inc.
-
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
-
This is free software: you are free to change and redistribute it.
-
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
-
and "show warranty" for details.
-
This GDB was configured as "i686-linux-gnu".
-
For bug reporting instructions, please see:
-
<http://www.gnu.org/software/gdb/bugs/>...
-
Reading symbols from /home/orisun/fork...done.
-
(gdb) set follow-fork-mode child
-
(gdb) set detach-on-fork off
-
(gdb) break 31
-
Breakpoint 1 at 0x80485e3: file fork.c, line 31.
-
(gdb) r
-
Starting program: /home/orisun/fork
-
[New process 13534]
-
[Switching to process 13534]
-
-
Breakpoint 1, main () at fork.c:31
-
if(shmdt(arr)==-1){
-
(gdb) p arr
-
$1 = 0xb7ffd000 "abc"
-
(gdb) c
-
Continuing.
-
-
Program exited normally.
-
(gdb)
阅读(1009) | 评论(0) | 转发(0) |