【gdb命令】只允许一个线程运行

只允许一个线程运行

使用gdb调试多线程程序时,默认的调试模式为:一个线程暂停运行,其它线程也随即暂停;一个线程启动运行,其它线程也随即启动。要知道,这种调试机制确实能帮我们更好地监控各个线程的“一举一动”,但并非适用于所有场景。一些场景中,我们可能只想让某一特定线程运行,其它线程仍维持暂停状态。要想达到这样的效果,就需要借助 set scheduler-locking 命令。 此命令可以帮我们将其它线程都“锁起来”,使后续执行的命令只对当前线程或者指定线程有效,而对其它线程无效。

set scheduler-locking 命令的语法格式如下:

命令 说明
set scheduler-locking mode on 不锁定线程,任何线程都可以随时执行
set scheduler-locking mode off 锁定线程,只有当前线程或指定线程可以运行
set scheduler-locking mode step 当单步执行某一线程时,其它线程不会执行,同时保证在调试过程中当前线程不会发生改变。但如果该模式下执行 continue、until、finish 命令,则其它线程也会执行,并且如果某一线程执行过程遇到断点,则 GDB 调试器会将该线程作为当前线程

1. 例子:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

int a = 0;
int b = 0;

void *thread1_func(void *p_arg)
{
  while (1)
  {
    a++;
    sleep(1);
  }
}

void *thread2_func(void *p_arg)
{
  while (1)
  {
    b++;
    sleep(1);
  }
}

int main(void)
{
  pthread_t t1, t2;

  pthread_create(&t1, NULL, thread1_func, "Thread 1");
  pthread_create(&t2, NULL, thread2_func, "Thread 2");

  sleep(1000);
  return 0;
}

用gdb调试多线程程序时,一旦程序断住,所有的线程都处于暂停状态。此时当你调试其中一个线程时(比如执行“step”,“next”命令),所有的线程都会同时执行。以上面程序为例:

(gdb) b demo.c:9
Breakpoint 1 at 0x400580: file demo.c, line 9.
(gdb) r
Starting program: /data2/home/nanxiao/demo.c
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7ffff782c700 (LWP 17368)]
[Switching to Thread 0x7ffff782c700 (LWP 17368)]

Breakpoint 1, thread1_func (p_arg=0x400718) at demo.c:9
9                       a++;
(gdb) p b
$1 = 0
(gdb) s
10                      sleep(1);
(gdb) s
[New Thread 0x7ffff6e2b700 (LWP 17369)]
11              }
(gdb)

Breakpoint 1, thread1_func (p_arg=0x400718) at demo.c:9
9                       a++;
(gdb)
10                      sleep(1);
(gdb) p b
$2 = 3

thread1_func更新全局变量a的值,thread2_func更新全局变量b的值。我在thread1_funca++语句打上断点,当断点第一次命中时,打印b的值是0,在单步调试thread1_func几次后,b的值变成3,证明在单步调试thread1_func时,thread2_func也在执行。
如果想在调试一个线程时,让其它线程暂停执行,可以使用“set scheduler-locking on”命令:

(gdb) b demo.c:9
Breakpoint 1 at 0x400580: file demo.c, line 9.
(gdb) r
Starting program: /data2/home/nanxiao/demo.c
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
[New Thread 0x7ffff782c700 (LWP 19783)]
[Switching to Thread 0x7ffff782c700 (LWP 19783)]

Breakpoint 1, thread1_func (p_arg=0x400718) at demo.c:9
9                       a++;
(gdb) set scheduler-locking on
(gdb) p b
$1 = 0
(gdb) s
10                      sleep(1);
(gdb)
11              }
(gdb)

Breakpoint 1, thread1_func (p_arg=0x400718) at demo.c:9
9                       a++;
(gdb)
10                      sleep(1);
(gdb)
11              }
(gdb) p b
$2 = 0

可以看到在单步调试thread1_func几次后,b的值仍然为0,证明在在单步调试thread1_func时,thread2_func没有执行。此外,“set scheduler-locking”命令除了支持offon模式外(默认是off),还有一个step模式。含义是:当用"step"命令调试线程时,其它线程不会执行,但是用其它命令(比如"next")调试线程时,其它线程也许会执行。

这个命令依赖于具体操作系统的调度策略,使用时需注意。

 

参考资料

1. gdb手册

2. 只允许一个线程运行

3. 

posted @ 2023-10-15 20:49  苏格拉底的落泪  阅读(687)  评论(0编辑  收藏  举报