Solaris
操作系统提供了pstack工具,用来打印运行程序的线程堆栈信息。RedHat
公司发行的Linux
操作系统(RHEL
,CentOS
等等)也提供了pstack
工具,只要安装gdb
:
# yum install gdb
就会把pstack
也一并安装成功。
首先看一下pstack
:
# which pstack
/usr/bin/pstack
# ls -lt /usr/bin/pstack
lrwxrwxrwx. 1 root root 6 Nov 19 06:32 /usr/bin/pstack -> gstack
可以看出pstack
实际上只是一个指向了gstack
的符号链接。再看一下gstack
:
# 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}
# Run GDB, strip out unwanted noise.
# --readnever is no longer used since .gdb_index is now in use.
$GDB --quiet -nx $GDBARGS /proc/$1/exe $1 <<EOF 2>&1 |
set width 0
set height 0
set pagination no
$backtrace
EOF
/bin/sed -n \
-e 's/^\((gdb) \)*//' \
-e '/^#/p' \
-e '/^Thread/p'
可以看到gstack
仅仅是一个shell
脚本。简单浏览一下这个脚本:
(1)
if test $# -ne 1; then
echo "Usage: `basename $0 .sh` <process-id>" 1>&2
exit 1
fi
脚本要求一个参数:进程ID
。
(2)
if test ! -r /proc/$1; then
echo "Process $1 not found." 1>&2
exit 1
fi
通过检测/proc
目录下进程子目录是否可读,来查看相应进程是否存在。
(3)
# 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
的“bt
”命令打印线程堆栈信息,否则使用“thread apply all bt
”命令。
(4)
GDB=${GDB:-/usr/bin/gdb}
# Run GDB, strip out unwanted noise.
# --readnever is no longer used since .gdb_index is now in use.
$GDB --quiet -nx $GDBARGS /proc/$1/exe $1 <<EOF 2>&1 |
set width 0
set height 0
set pagination no
$backtrace
EOF
/bin/sed -n \
-e 's/^\((gdb) \)*//' \
-e '/^#/p' \
-e '/^Thread/p'
最后调用gdb
,使用“bt
”或“thread apply all bt
”命令,并把输出重定向到sed
工具,由sed
工具打印出线程堆栈信息。
最后看一个使用pstack
的例子:
# pstack 707
Thread 3 (Thread 0x7f69600d8700 (LWP 713)):
#0 0x00007f6968af269d in poll () at ../sysdeps/unix/syscall-template.S:81
#1 0x00007f6969027a84 in g_main_context_iterate.isra.24 () from /lib64/libglib-2.0.so.0
#2 0x00007f6969027bac in g_main_context_iteration () from /lib64/libglib-2.0.so.0
#3 0x00007f6969027be9 in glib_worker_main () from /lib64/libglib-2.0.so.0
#4 0x00007f696904d4f5 in g_thread_proxy () from /lib64/libglib-2.0.so.0
#5 0x00007f696af9fdc5 in start_thread (arg=0x7f69600d8700) at pthread_create.c:308
#6 0x00007f6968afcced in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:113
Thread 2 (Thread 0x7f695eec3700 (LWP 716)):
#0 0x00007f6968af269d in poll () at ../sysdeps/unix/syscall-template.S:81
#1 0x00007f6969027a84 in g_main_context_iterate.isra.24 () from /lib64/libglib-2.0.so.0
#2 0x00007f6969027dca in g_main_loop_run () from /lib64/libglib-2.0.so.0
#3 0x00007f6969641336 in gdbus_shared_thread_func () from /lib64/libgio-2.0.so.0
#4 0x00007f696904d4f5 in g_thread_proxy () from /lib64/libglib-2.0.so.0
#5 0x00007f696af9fdc5 in start_thread (arg=0x7f695eec3700) at pthread_create.c:308
#6 0x00007f6968afcced in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:113
Thread 1 (Thread 0x7f696c5738c0 (LWP 707)):
#0 0x00007f6968af269d in poll () at ../sysdeps/unix/syscall-template.S:81
#1 0x00007f6969027a84 in g_main_context_iterate.isra.24 () from /lib64/libglib-2.0.so.0
#2 0x00007f6969027dca in g_main_loop_run () from /lib64/libglib-2.0.so.0
#3 0x0000560a080a80a3 in main ()
如果使用的Linux
发行版没有pstack
这个工具,可以考虑直接把gstack
脚本拷贝过去。
你好, 如果进程确实在, pstack 也安装了, 但是 执行pstack 后 没有打印,
Could not attach to target 28378: Operation not permitted.
detach: No such process
我尝试 用超级用户 没有输出, 28378: ./deadlock
(No symbols found in )
(No symbols found in /lib/i386-linux-gnu/libc.so.6)
(No symbols found in /lib/ld-linux.so.2)
crawl: Input/output error
Error tracing through process 28378
0xb779fce5: _fini + 0x25d51
请问具体是什么问题? 是Linux 分发版本的问题吗?