Board logo

标题: Linux on Power 上的调试工具和技术(4) [打印本页]

作者: look_w    时间: 2017-11-18 21:56     标题: Linux on Power 上的调试工具和技术(4)

多线程环境在 GDB 中有一些特殊的命令可以用于多线程应用程序的调试。下面这个例子给出了一个死锁情况,并介绍了如何使用这些命令来检查多线程应用程序中的问题:
清单 20.  多线程的例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <stdio.h>
#include "pthread.h>
pthread_mutex_t AccountA_mutex;
pthread_mutex_t AccountB_mutex;
struct BankAccount {
     char account_name[1];
     int balance;
};
struct BankAccount  accountA = {"A", 10000 };
struct BankAccount  accountB = {"B", 20000 };
void * transferAB (void* amount_ptr) {
     int amount = *((int*)amount_ptr);
     pthread_mutex_lock(&AccountA_mutex);
     if (accountA.balance < amount)   {
             printf("There is not enough memory in Account A!\n");
             pthread_mutex_unlock(&AccountA_mutex);
             pthread_exit((void *)1);
     }
     accountA.balance -=amount;
     sleep(1);
     pthread_mutex_lock(&AccountB_mutex);
     accountB.balance +=amount;
     pthread_mutex_unlock(&AccountA_mutex);
     pthread_mutex_unlock(&AccountB_mutex);
}
void * transferBA (void* amount_ptr) {
     int amount = *((int*)amount_ptr);
     pthread_mutex_lock(&AccountB_mutex);
     if (accountB.balance < amount)   {
             printf("There is not enough memory in Account B!\n");
             pthread_mutex_unlock(&AccountB_mutex);
             pthread_exit((void *)1);
     }
     accountB.balance -=amount;
     sleep(1);
     pthread_mutex_lock(&AccountA_mutex);
     accountA.balance +=amount;
     pthread_mutex_unlock(&AccountB_mutex);
     pthread_mutex_unlock(&AccountA_mutex);
}
int main(int argc, char* argv[]) {
     int             threadid[4];
     pthread_t       pthread[4];
     int             transfer_amount[4] = {100, 200, 300, 400};
     int             final_balanceA, final_balanceB;
     final_balanceA=accountA.balance-transfer_amount[0]-<br>
transfer_amount[1]+transfer_amount[2]+transfer_amount[3];
     final_balanceB=accountB.balance+transfer_amount[0]<br>
+transfer_amount[1]-transfer_amount[2]-transfer_amount[3];
     if (threadid[0] = pthread_create(&pthread[0], NULL, transferAB,
     (void*)&transfer_amount[0]) " 0) {
             perror("Thread #0 creation failed.");
             exit (1);
        }
     if (threadid[1] = pthread_create(&pthread[1], NULL, transferAB,
      (void*)&transfer_amount[1]) " 0) {
             perror("Thread #1 creation failed.");
             exit (1);
     }
     if (threadid[2] = pthread_create(&pthread[2], NULL, transferBA,
      (void*)&transfer_amount[2]) < 0) {
             perror("Thread #2 creation failed.");
             exit (1);
     }
     if (threadid[3] = pthread_create(&pthread[3], NULL, transferBA,
        (void*)&transfer_amount[3]) < 0) {
             perror("Thread #3 creation failed.");
             exit (1);
     }
     printf("Transitions are in progress..");
     while ((accountA.balance != final_balanceA) && (accountB.balance
             != final_balanceB)) {
             printf("..");
     }
     printf("\nAll the  money is transferred !!\n");
}




使用 gcc 来编译这个程序,如下所示:
1
# gcc -g -o gdbtest2 gdbtest2.c -L/lib/tls -lpthread




程序 gdbtest2 会挂起,不会返回一条 All the money is transferred !! 消息。
将 gdb 附加到正在运行的进程上,从而了解这个进程内部正在发生什么。
清单 21. 将 gdb 附加到正在运行的进程上
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# ps -ef |grep gdbtest2
root      9510  8065  1 06:30 pts/1    00:00:00 ./gdbtest2
root      9516  9400  0 06:30 pts/4    00:00:00 grep gdbtest2
# gdb -pid 9510
GNU gdb 6.2.1
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you
are welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for
details.
This GDB was configured as "ppc-suse-linux".
Attaching to process 9510
Reading symbols from /root/test/gdbtest2...done.
Using host libthread_db library "/lib/tls/libthread_db.so.1".
Reading symbols from /lib/tls/libpthread.so.0...done.
[Thread debugging using libthread_db enabled]
[New Thread 1073991712 (LWP 9510)]
[New Thread 1090771744 (LWP 9514)]
[New Thread 1086577440 (LWP 9513)]
[New Thread 1082383136 (LWP 9512)]
[New Thread 1078188832 (LWP 9511)]
Loaded symbols for /lib/tls/libpthread.so.0
Reading symbols from /lib/tls/libc.so.6...done.
Loaded symbols for /lib/tls/libc.so.6
Reading symbols from /lib/ld.so.1...done.
Loaded symbols for /lib/ld.so.1
0x0ff4ac40 in __write_nocancel () from /lib/tls/libc.so.6
(gdb) info thread
  5 Thread 1078188832 (LWP 9511)  0x0ffe94ec in __lll_lock_wait ()
   from /lib/tls/libpthread.so.0
  4 Thread 1082383136 (LWP 9512)  0x0ffe94ec in __lll_lock_wait ()
   from /lib/tls/libpthread.so.0
  3 Thread 1086577440 (LWP 9513)  0x0ffe94ec in __lll_lock_wait ()
   from /lib/tls/libpthread.so.0
  2 Thread 1090771744 (LWP 9514)  0x0ffe94ec in __lll_lock_wait ()
        from /lib/tls/libpthread.so.0
  1 Thread 1073991712 (LWP 9510)  0x0ff4ac40 in __write_nocancel ()
     from /lib/tls/libc.so.6
(gdb)




从 info thread 命令中,我们可以了解到除了主线程(thread #1)之外的所有线程都在等待函数 __lll_lock_wait () 完成。
使用 thread apply threadno where 命令来查看每个线程到底运行到了什么地方:




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0