gdb 笔记(11)— info 和 thread 命令(查看线程、切换线程)

info 命令是一个复合指令,还可以用来查看当前进程的所有线程运行情况。

下面以 redis-server 进程为例来演示一下,使用 delete 命令删掉所有断点,然后使用 run 命令重启一下 redis-server,等程序正常启动后,我们按快捷键 Ctrl+C 中断程序,然后使用 info thread 命令来查看当前进程有哪些线程,分别中断在何处:

(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/gdbtest/redis-4.0.11/src/redis-server
[Thread debugging using libthread_db enabled]
......
53062:M 10 Sep 17:11:10.810 * Ready to accept connections
^C
Program received signal SIGINT, Interrupt.
0x00007ffff73ee923 in epoll_wait () from /lib64/libc.so.6
(gdb) info thread
  Id   Target Id         Frame
  4    Thread 0x7fffef7fd700 (LWP 53065) "redis-server" 0x00007ffff76c4945 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
  3    Thread 0x7fffefffe700 (LWP 53064) "redis-server" 0x00007ffff76c4945 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
  2    Thread 0x7ffff07ff700 (LWP 53063) "redis-server" 0x00007ffff76c4945 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
* 1    Thread 0x7ffff7fec780 (LWP 53062) "redis-server" 0x00007ffff73ee923 in epoll_wait () from /lib64/libc.so.6

通过 info thread 的输出可以知道 redis-server 正常启动后,一共产生了 4 个线程,包括一个主线程和三个工作线程,线程编号(Id 那一列)分别是 4、3、2、1。三个工作线程(2、3、4)分别阻塞在 Linux API pthread_cond_wait 处,而主线程(1)阻塞在 epoll_wait 处。

注意 虽然第一栏的名称叫 Id,但第一栏的数值不是线程的 Id,第三栏括号里的内容(如 LWP 53065)中,53065 这样的数值才是当前线程真正的 Id。那 LWP 是什么意思呢?在早期的 Linux 系统的内核里面,其实不存在真正的线程实现,当时所有的线程都是用进程来实现的,这些模拟线程的进程被称为 Light Weight Process(轻量级进程),后来 Linux 系统有了真正的线程实现,这个名字仍然被保留了下来。

读者可能会有疑问:怎么知道线程 1 就是主线程?线程 2、线程 3、线程 4 就是工作线程呢?是不是因为线程 1 前面有个星号(*)?错了,线程编号前面这个星号表示的是当前 GDB 作用于哪个线程,而不是主线程的意思。现在有 4 个线程,也就有 4 个调用堆栈,如果此时输入 backtrace 命令查看调用堆栈,由于当前 GDB 作用在线程 1,因此 backtrace 命令显示的一定是线程 1 的调用堆栈:

(gdb) bt
#0  0x00007ffff73ee923 in epoll_wait () from /lib64/libc.so.6
#1  0x00000000004265df in aeApiPoll (tvp=0x7fffffffe300, eventLoop=0x7ffff08350a0) at ae_epoll.c:112
#2  aeProcessEvents (eventLoop=eventLoop@entry=0x7ffff08350a0, flags=flags@entry=11) at ae.c:411
#3  0x0000000000426aeb in aeMain (eventLoop=0x7ffff08350a0) at ae.c:501
#4  0x00000000004238ef in main (argc=1, argv=0x7fffffffe648) at server.c:3899

由此可见,堆栈 #4 的 main() 函数也证实了上面的说法,即线程编号为 1 的线程是主线程。

如何切换到其他线程呢?可以通过 thread 线程编号 切换到具体的线程上去。例如,想切换到线程 2 上去,只要输入 thread 2 即可,然后输入 bt 就能查看这个线程的调用堆栈了:

(gdb) info thread
  Id   Target Id         Frame
  4    Thread 0x7fffef7fd700 (LWP 53065) "redis-server" 0x00007ffff76c4945 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
  3    Thread 0x7fffefffe700 (LWP 53064) "redis-server" 0x00007ffff76c4945 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
  2    Thread 0x7ffff07ff700 (LWP 53063) "redis-server" 0x00007ffff76c4945 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
* 1    Thread 0x7ffff7fec780 (LWP 53062) "redis-server" 0x00007ffff73ee923 in epoll_wait () from /lib64/libc.so.6
(gdb) thread 2
[Switching to thread 2 (Thread 0x7ffff07ff700 (LWP 53063))]
#0  0x00007ffff76c4945 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
(gdb) bt
#0  0x00007ffff76c4945 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x000000000047a91c in bioProcessBackgroundJobs (arg=0x0) at bio.c:176
#2  0x00007ffff76c0e25 in start_thread () from /lib64/libpthread.so.0
#3  0x00007ffff73ee34d in clone () from /lib64/libc.so.6

因此利用 info thread 命令就可以调试多线程程序。请注意,当把 GDB 当前作用的线程切换到线程 2 上之后,线程 2 前面就被加上了星号:

(gdb) info thread
  Id   Target Id         Frame
  4    Thread 0x7fffef7fd700 (LWP 53065) "redis-server" 0x00007ffff76c4945 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
  3    Thread 0x7fffefffe700 (LWP 53064) "redis-server" 0x00007ffff76c4945 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
* 2    Thread 0x7ffff07ff700 (LWP 53063) "redis-server" 0x00007ffff76c4945 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
  1    Thread 0x7ffff7fec780 (LWP 53062) "redis-server" 0x00007ffff73ee923 in epoll_wait () from /lib64/libc.so.6

上面介绍的是 info 命令最常用的三种方法,更多关于 info 的组合命令在 GDB 中输入 help info 就可以查看:

(gdb) help info
Generic command for showing things about the program being debugged.

List of info subcommands:

info address -- Describe where symbol SYM is stored
info all-registers -- List of all registers and their contents
info args -- Argument variables of current stack frame
info auto-load -- Print current status of auto-loaded files
info auto-load-scripts -- Print the list of automatically loaded Python scripts
info auxv -- Display the inferior s auxiliary vector
info bookmarks -- Status of user-settable bookmarks
info breakpoints -- Status of specified breakpoints (all user-settable breakpoints if no argument)
info checkpoints -- IDs of currently known checkpoints
info classes -- All Objective-C classes
info common -- Print out the values contained in a Fortran COMMON block
info copying -- Conditions for redistributing copies of GDB
info dcache -- Print information on the dcache performance
info display -- Expressions to display when program stops
info extensions -- All filename extensions associated with a source language
info files -- Names of targets and files being debugged
info float -- Print the status of the floating point unit
info frame -- All about selected stack frame
info frame-filter -- List all registered Python frame-filters
info functions -- All function names
info handle -- What debugger does when program gets various signals
info inferiors -- IDs of specified inferiors (all inferiors if no argument)
info line -- Core addresses of the code for a source line
info locals -- Local variables of current stack frame
info macro -- Show the definition of MACRO
info macros -- Show the definitions of all macros at LINESPEC
info mem -- Memory region attributes
info os -- Show OS data ARG
info pretty-printer -- GDB command to list all registered pretty-printers
info probes -- Show available static probes
info proc -- Show /proc process information about any running process
info program -- Execution status of the program
info record -- Info record options
info registers -- List of integer registers and their contents
info scope -- List the variables local to a scope
---Type <return> to continue, or q <return> to quit---
info selectors -- All Objective-C selectors
info set -- Show all GDB settings
info sharedlibrary -- Status of loaded shared object libraries
info signals -- What debugger does when program gets various signals
info skip -- Display the status of skips
info source -- Information about the current source file
info sources -- Source files in the program
info stack -- Backtrace of the stack
info static-tracepoint-markers -- List target static tracepoints markers
info symbol -- Describe what symbol is at location ADDR
info target -- Names of targets and files being debugged
info tasks -- Provide information about all known Ada tasks
info terminal -- Print inferior's saved terminal status
info threads -- Display currently known threads
info tracepoints -- Status of specified tracepoints (all tracepoints if no argument)
info tvariables -- Status of trace state variables and their values
info type-printers -- GDB command to list all registered type-printers
info types -- All type names
info variables -- All global and static variable names
info vector -- Print the status of the vector unit
info vtbl -- Show the virtual function table for a C++ object
info warranty -- Various kinds of warranty you do not have
info watchpoints -- Status of specified watchpoints (all watchpoints if no argument)
info win -- List of all displayed windows

Type "help info" followed by info subcommand name for full documentation.
Type "apropos word" to search for commands related to "word".
Command name abbreviations are allowed if unambiguous.

参考:https://download.csdn.net/columnTopic/5c0e2061edba1b6834591ebc

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值