学习GDB这门课程,首先下载nanocode:
10.1假期前学习了gtk4,粗通后准备改造一下张老师的程序:
https://github.com/gedulab/silklock/blob/main/silklock.cpp
Makefile说明:
all: silklock
silklock: silklock.cpp boxboss.cpp chairman.cpp
g++ -g3 $^ -o $@ `pkg-config --cflags --libs gtk+-2.0 gthread-2.0`
clean:
rm silklock
$^:
$@:
https://ninja-build.org/
$@ 和 $^ 都是 Make 的内设变量,也可以看成是一种类似 C 语言中宏的东西。
$@ 在指令被运行时,被宏替换为目标,
而 $^ 被宏替换为所有的依赖目标,即冒号后面的那一长串东西。
同样常用的还是 $< ,可以替换所依赖的第一个目标。
这个程序我看是2023年上传的,用的是gtk2,在我的机器上死活跑不起来,界面直接死掉退出。估计是我的ubuntu版本太新了,运行gtk2有问题。假期出去几天,10.6开始在家休息两天,这两天仔细研究了这个程序,终于将gtk2迁移改造为gtk4,可以在我的ubuntu 上运行了。不过有个缺点,就是界面不能换行,加了\n就运行异常,估计还是没有学好gtk4。这也不影响使用GDB调试这个多线程程序,让我们开始结合这个slock.cpp(我缩短了文件名称)来操练gdb多线程调试吧。
先介绍一下GTK4的Makefile配置,与GTK2不同:gtk+-2.0变成了gtk4,不再需要gthread,因为thread已经是C++标准库的一部分了,无需特别说明。
:~/gelabs/gtk$ cat Makefile
all: slock
slock: slock.cpp boxboss.cpp chairman.cpp
g++ -g3 $^ -o $@ `pkg-config --cflags --libs gtk4`
clean:
rm slock
然后开始操练程序:
(gdb) bt
#0 0x00007f41b087b4cd in __GI___poll (fds=0x556a36a2dcd0, nfds=2, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
#1 0x00007f41b0cda66e in ??? () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#2 0x00007f41b0c7aa53 in g_main_context_iteration () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#3 0x00007f41b0eb188d in g_application_run () at /lib/x86_64-linux-gnu/libgio-2.0.so.0
#4 0x0000556a2e364efd in main (argc=1, argv=0x7ffdcfcba138) at slock.cpp:139
这个线程是UI线程,UI线程当前执行到了GI_poll
(gdb) info args --info看参数
fds = 0x556a36a2dcd0
nfds = 2
timeout = -1
(gdb) p fds --print看变量
$1 = (struct pollfd *) 0x556a36a2dcd0
(gdb) pt fds --pt看类型
type = struct pollfd {
int fd;
short events;
short revents;
} *
(gdb) p fds[0]@2 --print数组的前2个
$2 = {
{fd = 3, events = 1, revents = 0}, {fd = 8, events = 1, revents = 0}}
其中的fd=3,fd=8是什么?可以通过lsof来获取
进程ID是30133
(gdb) !lsof -p 30133 --列出打开的文件描述符
lsof: WARNING: can't stat() fuse.portal file system /run/user/1001/doc
Output information may be incomplete.
lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1001/gvfs
Output information may be incomplete.
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
slock 30133 zxl 3u a_inode 0,14 0 13557 [eventfd:165]
slock 30133 zxl 4u a_inode 0,14 0 13557 [eventfd:166]
slock 30133 zxl 5u unix 0xffff8de34994e600 0t0 174584 type=STREAM (CONNECTED)
slock 30133 zxl 6u a_inode 0,14 0 13557 [eventfd:167]
slock 30133 zxl 7r a_inode 0,14 0 13557 inotify
slock 30133 zxl 8u IPv4 174590 0t0 TCP localhost:33258->localhost:6010 (ESTABLISHED)
3号和8号文件描述符上面标红了。eventfd就是事件使用的,比如鼠标键盘事件。UI程序是比较复杂的,要处理这种事件。
这个UI线程在等消息,没有啥问题,下面继续看其他线程:
info threads --列出进程中的所有线程。
(gdb) info threads
Id Target Id Frame
* 1 Thread 0x7f41af756e40 (LWP 30133) "slock" 0x00007f41b087b4cd in __GI___poll (fds=0x556a36a2dcd0, nfds=2,
timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
2 Thread 0x7f414e7fc6c0 (LWP 30177) "slock" 0x0000556a2e3654a8 in MasterThreadProc (p=0x556a2e36c0a0 <boss>)
at boxboss.cpp:122
3 Thread 0x7f412dffb6c0 (LWP 30175) "slock" futex_wait (private=0, expected=2,
futex_word=0x556a2e36c0c8 <boss+40>) at ../sysdeps/nptl/futex-internal.h:146
4 Thread 0x7f412effd6c0 (LWP 30173) "slock" futex_wait (private=0, expected=2,
futex_word=0x556a2e36c0c8 <boss+40>) at ../sysdeps/nptl/futex-internal.h:146
5 Thread 0x7f412f7fe6c0 (LWP 30172) "slock" futex_wait (private=0, expected=2,
futex_word=0x556a2e36c0c8 <boss+40>) at ../sysdeps/nptl/futex-internal.h:146
6 Thread 0x7f412ffff6c0 (LWP 30171) "slock" (Exiting) futex_wait (private=0, expected=2,
futex_word=0x556a2e36c0c8 <boss+40>) at ../sysdeps/nptl/futex-internal.h:146
7 Thread 0x7f414dffb6c0 (LWP 30168) "slock" futex_wait (private=0, expected=2,
futex_word=0x556a2e36c0c8 <boss+40>) at ../sysdeps/nptl/futex-internal.h:146
8 Thread 0x7f416f7fe6c0 (LWP 30167) "slock" futex_wait (private=0, expected=2,
futex_word=0x556a2e36c0c8 <boss+40>) at ../sysdeps/nptl/futex-internal.h:146
9 Thread 0x7f416ffff6c0 (LWP 30146) "slock:disk$0" 0x00007f41b07f8d61 in __futex_abstimed_wait_common64 (private=0,
cancel=true, abstime=0x0, op=393, expected=0, futex_word=0x556a2e6b4d38) at ./nptl/futex-internal.c:57
10 Thread 0x7f418cc246c0 (LWP 30145) "slock" 0x00007f41b07f8d61 in __futex_abstimed_wait_common64 (
private=32577, cancel=true, abstime=0x0, op=393, expected=0, futex_word=0x556a2e76e8d0) at ./nptl/futex-internal.c:57
11 Thread 0x7f418d4256c0 (LWP 30144) "slock" 0x00007f41b07f8d61 in __futex_abstimed_wait_common64 (
private=32577, cancel=true, abstime=0x0, op=393, expected=0, futex_word=0x556a2e76e8d0) at ./nptl/futex-internal.c:57
12 Thread 0x7f418dc266c0 (LWP 30143) "slock" 0x00007f41b07f8d61 in __futex_abstimed_wait_common64 (
private=32577, cancel=true, abstime=0x0, op=393, expected=0, futex_word=0x556a2e76e8d0) at ./nptl/futex-internal.c:57
13 Thread 0x7f418e4276c0 (LWP 30142) "slock" 0x00007f41b07f8d61 in __futex_abstimed_wait_common64 (
private=32577, cancel=true, abstime=0x0, op=393, expected=0, futex_word=0x556a2e76e8d0) at ./nptl/futex-internal.c:57
14 Thread 0x7f418ec286c0 (LWP 30141) "llvmpipe-3" 0x00007f41b07f8d61 in __futex_abstimed_wait_common64 (private=0,
cancel=true, abstime=0x0, op=393, expected=0, futex_word=0x556a2e75f628) at ./nptl/futex-internal.c:57
15 Thread 0x7f419cbff6c0 (LWP 30140) "llvmpipe-2" 0x00007f41b07f8d61 in __futex_abstimed_wait_common64 (private=0,
cancel=true, abstime=0x0, op=393, expected=0, futex_word=0x556a2e75f4cc) at ./nptl/futex-internal.c:57
16 Thread 0x7f419d4006c0 (LWP 30139) "llvmpipe-1" 0x00007f41b07f8d61 in __futex_abstimed_wait_common64 (private=0,
cancel=true, abstime=0x0, op=393, expected=0, futex_word=0x556a2e75f368) at ./nptl/futex-internal.c:57
17 Thread 0x7f419dc016c0 (LWP 30138) "llvmpipe-0" 0x00007f41b07f8d61 in __futex_abstimed_wait_common64 (private=0,
cancel=true, abstime=0x0, op=393, expected=0, futex_word=0x556a2e75f208) at ./nptl/futex-internal.c:57
18 Thread 0x7f41ad6926c0 (LWP 30137) "slock" syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
19 Thread 0x7f41ade936c0 (LWP 30136) "gdbus" 0x00007f41b087b4cd in __GI___poll (fds=0x7f41a4000b90, nfds=3,
--Type <RET> for more, q to quit, c to continue without paging--
timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
20 Thread 0x7f41ae6b56c0 (LWP 30135) "gmain" 0x00007f41b087b4cd in __GI___poll (fds=0x556a2e6c08e0, nfds=2,
timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:29
21 Thread 0x7f41aeeb66c0 (LWP 30134) "pool-spawner" syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
21个线程,3种状态:
- Poll
- wait
- 正在跑
正在跑的只有2号线程,切换到2号线程,list看看:
(gdb) thread 2
[Switching to thread 2 (Thread 0x7f414e7fc6c0 (LWP 30177))]
#0 0x0000556a2e3654a8 in MasterThreadProc (p=0x556a2e36c0a0 <boss>) at boxboss.cpp:122
122 while(pBoss->m_dwThreadCount != pBoss->m_dwCalcThreads) {
(gdb) l
117 uint32_t MasterThreadProc(void* p) {
118 CBoxBoss *pBoss = (CBoxBoss *)p;
119 uint32_t i;
120 d4d(_T("Master thread entered..."));
121
122 while(pBoss->m_dwThreadCount != pBoss->m_dwCalcThreads) {
123
124 }
125 pBoss->m_dResult = 0;
126 for(i=0;i<pBoss->m_dwCalcThreads;i++) {
(gdb) bt
#0 0x0000556a2e3654a8 in MasterThreadProc (p=0x556a2e36c0a0 <boss>) at boxboss.cpp:122
#1 0x0000556a2e36774f in std::__invoke_impl<unsigned int, unsigned int (*)(void*), CBoxBoss*>
(__f=@0x556a374c2a00: 0x556a2e36546d <MasterThreadProc(void*)>) at /usr/include/c++/13/bits/invoke.h:61
#2 0x0000556a2e367624 in std::__invoke<unsigned int (*)(void*), CBoxBoss*>
(__fn=@0x556a374c2a00: 0x556a2e36546d <MasterThreadProc(void*)>) at /usr/include/c++/13/bits/invoke.h:96
#3 0x0000556a2e367537 in std::thread::_Invoker<std::tuple<unsigned int (*)(void*), CBoxBoss*> >::_M_in