Chinaunix首页 | 论坛 | 博客
  • 博客访问: 458314
  • 博文数量: 80
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1916
  • 用 户 组: 普通用户
  • 注册时间: 2013-07-11 22:01
个人简介

从事实时计算多年,熟悉jstorm/spark/flink/kafka/rocketMq, 热衷于开源,希望在这里和前辈们一起学习与分享,得到长足的进步!邮箱:hustfxj@gmail.com 我的githup地址是:https://github.com/hustfxj。欢迎和大家一起交流探讨问题。

文章分类

全部博文(80)

文章存档

2017年(11)

2015年(3)

2014年(33)

2013年(33)

分类: LINUX

2014-02-13 18:02:13

        常常我们会碰到在多进程程序中,利用GDB无法调试子进程问题。实际上,GDB 没有对多进程程序调试提供直接支持。例如,使用GDB调试某个进程,如果该进程fork了子进程,GDB会继续调试该进程,子进程会不受干扰地运行下去。如果你事先在子进程代码里设定了断点,子进程会收到SIGTRAP信号并终止。那么该如何调试子进程呢?其实我们可以利用GDB的特点或者其他一些辅助手段来达到目的。此外,GDB 也在较新内核上加入一些多进程调试支持。

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <unistd.h>

  3. int main()
  4. ...{
  5.     if(fork() == 0)
  6.     ...{
  7.         printf("Child Process say hello to you! ");
  8.         sleep(5);
  9.         exit(0);
  10.     }
  11.     else
  12.         printf("Parent Process, Hello ");
  13.              
  14.     return 0;
  15. }
方法一:

ubuntu默认情况下你在gdb中使用attach id是权限不够的,所以你需要:sudo chmod +s /usr/bin/gdb

  1. 父子进程中加一句while(pause) sleep(1);,让其暂停,然后后台运行程序,通过ps获取子进程的PID。(如下所示,ps显示的./fork有两个,orisun是进程的有效用户,第一个数字是进程ID,第二个数字是其父进程ID)
  2. 运行gdb,attach 子进程ID

  1. orisun@zcypc:~$ ./fork &
  2. [1] 13294
  3. orisun@zcypc:~$ ps -ef|grep fork
  4.        790 1 0 09:00 ? 00:00:01 dbus-daemon --system --fork --activation=upstart
  5. orisun 1546 1 0 09:00 ? 00:00:03 //bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session
  6. orisun 12584 1 0 20:23 ? 00:00:12 gedit /home/orisun/fork.c
  7. orisun 13294 13239 0 20:53 pts/0 00:00:00 ./fork
  8. orisun 13295 13294 0 20:53 pts/0 00:00:00 ./fork
  9. orisun 13297 13239 0 20:54 pts/0 00:00:00 grep --color=auto fork
  10. orisun@zcypc:~$ gdb
  11. GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
  12. Copyright (C) 2010 Free Software Foundation, Inc.
  13. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  14. This is free software: you are free to change and redistribute it.
  15. There is NO WARRANTY, to the extent permitted by law. Type "show copying"
  16. and "show warranty" for details.
  17. This GDB was configured as "i686-linux-gnu".
  18. For bug reporting instructions, please see:
  19. <http://www.gnu.org/software/gdb/bugs/>.
  20. (gdb) attach 13295
  21. Attaching to process 13295
  22. Reading symbols from /home/orisun/fork...done.
  23. 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.
  24. done.
  25. Loaded symbols for /lib/i386-linux-gnu/libc.so.6
  26. Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
  27. Loaded symbols for /lib/ld-linux.so.2
  28. 0x00bd8416 in __kernel_vsyscall ()
  29. (gdb) backtrace
  30. #0 0x00bd8416 in __kernel_vsyscall ()
  31. #1 0x0049bfc0 in __nanosleep_nocancel ()
  32.     at ../sysdeps/unix/syscall-template.S:82
  33. #2 0x0049bde2 in __sleep (seconds=<value optimized out>)
  34.     at ../sysdeps/unix/sysv/linux/sleep.c:138
  35. #3 0x08048595 in main () at fork.c:25
  36. (gdb) up 3
  37. #3 0x08048595 in main () at fork.c:25
  38.            while(pause) sleep(1);
  39. (gdb) list
  40.        if((pid=fork())<0){
  41.            perror("fork");
  42.            exit(1);
  43.        }
  44.        if(pid==0){
  45.            while(pause) sleep(1);
  46.            if((arr=shmat(shmid,NULL,0))==(void*)-1){ //子进程中把共享内存映射到本,进行修改
  47.                perror("shmat");
  48.                exit(1);
  49.            }
  50. (gdb) break 31
  51. Breakpoint 1 at 0x8048600: file fork.c, line 31.
  52. (gdb) set pause=0
  53. (gdb) continue
  54. Continuing.

  55. Breakpoint 1, main () at fork.c:31
  56.            if(shmdt(arr)==-1){
  57. (gdb) p arr
  58. $1 = 0xb77fb000 "abc"
  59. (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)状态。

  1. orisun@zcypc:~$ gdb ./fork
  2. GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
  3. Copyright (C) 2010 Free Software Foundation, Inc.
  4. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
  5. This is free software: you are free to change and redistribute it.
  6. There is NO WARRANTY, to the extent permitted by law. Type "show copying"
  7. and "show warranty" for details.
  8. This GDB was configured as "i686-linux-gnu".
  9. For bug reporting instructions, please see:
  10. <http://www.gnu.org/software/gdb/bugs/>...
  11. Reading symbols from /home/orisun/fork...done.
  12. (gdb) set follow-fork-mode child
  13. (gdb) set detach-on-fork off
  14. (gdb) break 31
  15. Breakpoint 1 at 0x80485e3: file fork.c, line 31.
  16. (gdb) r
  17. Starting program: /home/orisun/fork
  18. [New process 13534]
  19. [Switching to process 13534]

  20. Breakpoint 1, main () at fork.c:31
  21.            if(shmdt(arr)==-1){
  22. (gdb) p arr
  23. $1 = 0xb7ffd000 "abc"
  24. (gdb) c
  25. Continuing.

  26. Program exited normally.
  27. (gdb)

阅读(3267) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~