GDB调试信号、多线程、多进程

GDB的功能很强大,本文主要介绍用GDB来调试信号、多进程、多线程,具体如下:

(一)信号

GDB有能力在你调试程序的时候处理任何一种信号,你可以告诉GDB需要处理哪一种信号。你可以要求GDB收到你所指定的信号时,马上停住正在运行的程序,以供你进行调试。你可以用GDB的handle命令来完成这一功能。

    handle <signal> <keywords...>
        在GDB中定义一个信号处理。信号<signal>可以以SIG开头或不以SIG开头,可以用定义一个要处理信号的范围(如:SIGIO- SIGKILL,表示处理从SIGIO信号到SIGKILL的信号,其中包括SIGIO, SIGIOT,SIGKILL三个信号),也可以使用关键字 all来标明要处理所有的信号。一旦被调试的程序接收到信号,运行程序马上会被GDB停住,以供调试。其<keywords>可以是以下几种关键字的一个或多个。

        nostop
            当被调试的程序收到信号时,GDB不会停住程序的运行,但会打出消息告诉你收到这种信号。
        stop
            当被调试的程序收到信号时,GDB会停住你的程序。
        print
            当被调试的程序收到信号时,GDB会显示出一条信息。
        noprint
            当被调试的程序收到信号时,GDB不会告诉你收到信号的信息。
        pass
        noignore
            当被调试的程序收到信号时,GDB不处理信号。这表示,GDB会把这个信号交给被调试程序会处理。
        nopass
        ignore
            当被调试的程序收到信号时,GDB不会让被调试程序来处理这个信号。

    info signals
    info handle
    查看有哪些信号在被GDB检测中。

(二)线程

如果你程序是多线程的话,你可以定义你的断点是否在所有的线程上,或是在某个特定的线程。GDB很容易帮你完成这一工作。

    break <linespec> thread <threadno>
    break <linespec> thread <threadno> if ...
        linespec指定了断点设置在的源程序的行号。threadno指定了线程的ID,注意,这个ID是GDB分配的,你可以通过“info threads”命令来查看正在运行程序中的线程信息。如果你不指定
thread <threadno>则表示你的断点设在所有线程上面。你还可以为某线程指定断点条件。如:

        (gdb) break frik.c:13 thread 28 if bartab > lim

    当你的程序被GDB停住时,所有的运行线程都会被停住。这方便你你查看运行程序的总体情况。而在你恢复程序运行时,所有的线程也会被恢复运行。那怕是主进程在被单步调试时。

线程有自己的寄存器,运行时堆栈或许还会有私有内存。   
gdb提供了以下供调试多线程的进程的功能:   
*   自动通告新线程。   
*   \ "thread   THREADNO\ ",一个用来在线程之间切换的命令。   
*   \ "info   threads\ ",一个用来查询现存线程的命令。   
*   \ "thread   apply   [THREADNO]   [ALL]   ARGS\ ",一个用来向线程提供命令的命令。   
*   线程有关的断点设置。   
注意:这些特性不是在所有gdb版本都能使用,归根结底要看操作系统是否支持。   
如果你的gdb不支持这些命令,会显示出错信息:   
(gdb)   info   threads   
(gdb)   thread   1   
Thread   ID   1   not   known.   Use   the   \ "info   threads\ "   command   to   
see   the   IDs   of   currently   known   threads.   
gdb的线程级调试功能允许你观察你程序运行中所有的线程,但无论什么时候   
gdb控制,总有一个“当前”线程。调试命令对“当前”进程起作用。   
一旦gdb发现了你程序中的一个新的线程,它会自动显示有关此线程的系统信   
息。比如:   
[New   process   35   thread   27]   
不过格式和操作系统有关。   
为了调试的目的,gdb自己设置线程号。   
`info   threads\ "   
显示进程中所有的线程的概要信息。gdb按顺序显示:   
1.线程号(gdb设置)   
2.目标系统的线程标识。   
3.此线程的当前堆栈。   
一前面打\ "*\ "的线程表示是当前线程。   
例如:   
(gdb)   info   threads   
3   process   35   thread   27   0x34e5   in   sigpause   ()   
2   process   35   thread   23   0x34e5   in   sigpause   ()   
*   1   process   35   thread   13   main   (argc=1,   argv=0x7ffffff8)   
at   threadtest.c:68   
`thread   THREADNO\ "   
把线程号为THREADNO的线程设为当前线程。命令行参数THREADNO是gdb内定的   
线程号。你可以用\ "info   threads\ "命令来查看gdb内设置的线程号。gdb显示该线程   
的系统定义的标识号和线程对应的堆栈。比如:   

(gdb)   thread   2   
[Switching   to   process   35   thread   23]   
0x34e5   in   sigpause   ()   
\ "Switching后的内容取决于你的操作系统对线程标识的定义。   

`thread   apply   [THREADNO]   [ALL]   ARGS\ "   
此命令让你对一个以上的线程发出相同的命令\ "ARGS\ ",[THREADNO]的含义同上。   
如果你要向你进程中的所有的线程发出命令使用[ALL]选项。   
无论gdb何时中断了你的程序(因为一个断点或是一个信号),它自动选择信号或   
断点发生的线程为当前线程。gdb将用一个格式为\ "[Switching   to   SYSTAG]\ "的消息   
来向你报告。   

 

(三)进程

1. 用的是attach子进程的方法
attach到正在运行的进程的功能,即attach <pid>命令。因此我们可以利用该命令attach到子进程然后进行调试。

一般的步骤是  1.首先要在要调试的子进程初始代码中,加入一段特殊代码,使子进程睡眠等待,然后运行待调试的程序
2.用ps -ef |grep 查看产生的子进程pid
3. 然后gdb启动,attach <pid>到进程后在该代码段后设上断点,就可以调试了

eg.

        pid = fork();
if (pid <0) {
printf("fork err\n");
exit(-1);
} else if (pid == 0) {
/* in child */
sleep(60); ------------------ (!)

int     value   = 10;

**********
} /**in parent****/

执行程序(比如说是 examp)
examp &   --- 让examp后台运行吧。(不后台运行也可以);

查找进程id:
ps -ef

运行gdb:
gdb
(gdb) attach xxxxx  --- xxxxx为利用ps命令获得的子进程 id
(gdb) stop --- 这点很重要,你需要先暂停那个子进程,然后设置一些断点和一些Watch
(gdb) break xx 
Breakpoint 1 at 0x10808: file eg1.c, line 37.
(gdb) c
Continuing.

2. 使用follow-fork-mode 的方法调试多进程
最好使用GDB 6.6或以上版本

使用follow-fork-mode 的方法调试多进程时的一般步骤是:
1.启动gdb 
2设置set follow-fork-mode [child/parent] 想调试child就使用child参数,如调试parent则使用parent
3启动程序文件 file ./hello ----------当然路径名自己要搞对哦
4.break num -----------如调试子进程则num是子进程代码的行数,
还有个小技巧就是break fork也就是在fork函数处设置断点.


原文:http://blog.csdn.net/yanook/article/details/6585648

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值