1 作用
pstack可以查看进程所有线程运行函数调用栈的情况。
2 命令
pstack pid
[~]$ pstack 11566
Thread 22 (Thread 1093765472 (LWP 12530)):
#0 0x000000302b80b5e0 in __recvfrom_nocancel ()
#1 0x0000000001184518 in heartbeat_server::udp_listen_thread ()
#2 0x0000000001183fcd in heartbeat_server::listen_thread ()
#3 0x0000000001183565 in listen_thread_func ()
#4 0x000000302b80610a in start_thread () from /lib64/tls/libpthread.so.0
#5 0x000000302afc6003 in clone () from /lib64/tls/libc.so.6
#6 0x0000000000000000 in ?? ()
Thread 21 (Thread 1104255328 (LWP 12531)):
#0 0x000000302af8f1a5 in __nanosleep_nocancel () from /lib64/tls/libc.so.6
#1 0x000000302afbf828 in usleep () from /lib64/tls/libc.so.6
#2 0x0000000001184fa5 in heartbeat_server::detect_thread ()
#3 0x0000000001183589 in detect_thread_func ()
#4 0x000000302b80610a in start_thread () from /lib64/tls/libpthread.so.0
#5 0x000000302afc6003 in clone () from /lib64/tls/libc.so.6
#6 0x0000000000000000 in ?? ()
Thread 20 (Thread 1116227936 (LWP 12532)):
#0 0x000000302b80b5e0 in __recvfrom_nocancel ()
#1 0x00000000011893d4 in heartbeat_client::udp_listen_thread ()
#2 0x0000000001189207 in heartbeat_client::listen_thread ()
#3 0x0000000001188c67 in listen_thread_func ()
#4 0x000000302b80610a in start_thread () from /lib64/tls/libpthread.so.0
#5 0x000000302afc6003 in clone () from /lib64/tls/libc.so.6
#6 0x0000000000000000 in ?? ()
……
Thread 1 (Thread 139714709505856 (LWP 11566)):
#0 0x000000302afc63dc in epoll_wait () from /lib64/tls/libc.so.6
#1 0x000000000109cc91 in ependingpool::pool_epoll_wait ()
#2 0x000000000109bc6f in ependingpool::check_item ()
#3 0x0000000000a56401 in get_ui_req_sock ()
#4 0x0000000000a565be in get_request_keepalive ()
#5 0x00000000009b8087 in Server ()
#6 0x00000000009b81e9 in USMain ()
#7 0x00000000009b71a3 in main ()
3 原理
其实pstack命令是一个shell脚本,通过调用gdb来打印了进程运行时的函数调用栈。OMG,强大的gdb
#!/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 `ls /proc/$1/task | 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 grep -e libpthread /proc/$1/maps > /dev/null 2>&1 ; then
backtrace="thread apply all bt"
fi
fi
GDB=${GDB:-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
sed -n \
-e 's/^(gdb) //' \
-e '/^#/p' \
-e '/^Thread/p'