pstack

pstack:查看进程调用栈

使用:pstack  进程号

原理:查看pstack命令,可以看到pstack是gstack的软链接。(注意:笔者是使用的centos,ubuntu等可能有区别)

gstack:又是一个脚本。两者都位于usr/bin/下

1 [xxxxx]#ls /usr/bin/pstack -la
2 lrwxrwxrwx. 1 root root 6 Jul  9 12:04 /usr/bin/pstack -> gstack

gstack源码读者可在如usr/bin/下找到

 

[root@localhost ~]# cat /usr/bin/gstack
#!/bin/sh

#判断入参个数是否大于1
if test $# -ne 1; then
    echo "Usage: `basename $0 .sh` <process-id>" 1>&2
    exit 1
fi

#判断/proc/下,入参的进程PID是否存在
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"
#新版本kernel,通过判断/proc/ /task/下数量判断是否为多线程
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
#旧版本kernel,通过判断/proc/ /maps下libpthread 数量判断是否为多线程
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'

 

脚本意思如下

(1)开始拦截命令携带参数个数

(2)查看进程是否存在 ,在/proc/下查看进程号

(3)注释描述需要判断什么情况时有thread apply all bt 还是bt命令。进程中存在多线程时时有thread apply all bt,进程只有一个线程时使用bt

(4)如果是新版本内核,则使用/proc/PID/task  判断是否为多线程,如果为老版本内核则使用 /proc/PID/maps。判断进程是否为多线程,/proc/PID/task/  下是否只有一个文件(线程号) 。   ls   /proc/PID/task | wc -l   查看线程个数,后者对于新版本内核其实不准确,因为单线程中一样能存在libpthread(编译的时候人为链接libpthread,已实验证实确实不准确)

(5)启动gdb 执行(3)处选择的命令打印堆栈。

 

posted on 2021-06-24 22:19  红旗kernel  阅读(596)  评论(0编辑  收藏  举报

导航