能否实现获取指定进程的调用堆栈信息?

我们知道调用backtrace()可以获取当前进程的调用堆栈信息,那如果想要获取另外一个进程(我们当然知道这个进程的pid)的调用堆栈信息,是否有办法呢?

stackoverflow上,就有人提出了这个问题,有网友给出的答案是向该进程发出一个信号,然后由该进程在信号处理函数里获取自身的调用堆栈,然后再发回来…。先不管这种方法行或不行,但至少不适合一般情况,因为它需要在指定进程里进行信号处理。

想想gdb工具,gdb几乎可以attach到任何进程上,在无需其它进程做任何额外工作的情况下,获取它的当前调用堆栈信息,所以说,回到题目问题,能够实现获取指定进程的调用堆栈信息,而恰好就有这么一个特定的工具pstack

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost ~]# pstack 4468
Thread 2 (Thread 0x4166f940 (LWP 4469)):
#0  0x00007fbcaf6e6b99 in pthread_cond_wait@@GLIBC_2.3.2 ()
#1  0x00007fbcb071e9fb in ?? () from /proc/4468/exe
#2  0x00007fbcaf6e24a7 in start_thread () from /lib64/libpthread.so.0
#3  0x00007fbcaf9cac2d in clone () from /lib64/libc.so.6
Thread 1 (Thread 0x7fbcb06f46e0 (LWP 4468)):
#0  0x00007fbcaf9cb018 in epoll_wait () from /lib64/libc.so.6
#1  0x00007fbcb072800c in ?? () from /proc/4468/exe
#2  0x00007fbcb0726fec in ?? () from /proc/4468/exe
#3  0x00007fbcb071d319 in main () from /proc/4468/exe
[root@localhost ~]#

从上实例可以看到,pstack可以获取指定进程(通过进程id)的所有线程调用堆栈信息,怎么做到的呢?其实pstack就是一个利用gdb实现的shell脚本:

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
[root@localhost ~]# ls -l `which pstack`
lrwxrwxrwx 1 root root 6 Jul 14  2010 /usr/bin/pstack -> gstack
[root@localhost ~]# file /usr/bin/gstack
/usr/bin/gstack: Bourne shell script text executable
[root@localhost ~]# cat !$
cat /usr/bin/gstack
#!/bin/sh
 
if test $# -ne 1; then
     echo "Usage: `basename $0 .sh` <process-id>" 1>&2
     exit 1
fi
 
if test ! -r /proc/$1; then
     echo "Process $1 not found." 1>&2
     exit 1
fi
 
# GDB doesn't allow "thread apply all bt" when the process isn't
# threaded; need to peek at the process to determine if that or the
# simpler "bt" should be used.
 
backtrace= "bt"
if test -d /proc/$1/task ; then
     # Newer kernel; has a task/ directory.
     if test `/bin/ls /proc/$1/task | /usr/bin/wc -l` -gt 1 2>/dev/null ; then
     backtrace= "thread apply all bt"
     fi
elif test -f /proc/$1/maps ; then
     # Older kernel; go by it loading libpthread.
     if /bin/grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then
     backtrace= "thread apply all bt"
     fi
fi
 
GDB=${GDB:-/usr/bin/gdb}
 
if $GDB -nx --quiet --batch --readnever > /dev/null 2>&1; then
     readnever=--readnever
else
     readnever=
fi
 
# Run GDB, strip out unwanted noise.
$GDB --quiet $readnever -nx /proc/$1/exe $1 <<EOF 2>&1 |
$backtrace
EOF
/bin/sed -n \
     -e 's/^(gdb) //' \
     -e '/^#/p' \
     -e '/^Thread/p'
[root@localhost ~]#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值