Ubuntu下程序进程堆栈信息——gstack

前言

在Ubuntu下调试程序,大部分是启动前使用gdb进行调试,当然也有其他方法,程序在运行中,为了不打断程序正常运行,也有一些工具进行调试。

当前本文章旨在说明不安装其他额外程序或库(除gdb外),并且在程序占用CPU过高想查看那些函数或库导致的,可使用如下方式。

Gstack

查看进程堆栈信息,Java推出jstack可以查看,C++也可以使用名为gstack命令进行查看,在本文作者查找gstack如何在ubuntu安装时遇到问题,只看到有gstack命令使用或介绍,并为搜索到安装命令,但在外网有幸找到,使用起来也挺方便,基本思路如下:

  1. 自己编写的程序CPU占用较高,程序名为`talker`
  2. 查看自己程序pid,如当前程序`talker`主进程号为:18666
  3. 使用Top -Hp 18666查看线程号,锁定占用CPU过高进程,如18677
  4. 使用gstack 18677,可打印堆栈信息,并得出所在库或函数占用较高问题

代码

关于gstack代码如下,创建名为`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 | 
set width 0
set height 0
set pagination no
$backtrace
EOF
/bin/sed -n \
    -e 's/^\((gdb) \)*//' \
    -e '/^#/p' \
    -e '/^Thread/p'
#end

保存后,将此文件赋予可执行权限如:

sudo chmod 777 gstack

随后将此文件存放至/usr/bin下

sudo cp gstack  /usr/bin/

至此gstack安装完毕

使用

假设,当前程序`talker`程序占用较高,查看pid得出:

test@test:~$ ps -ef | grep talker
test     18666 12982  0 16:07 pts/11   00:00:00 /opt/ros/kinetic/lib/roscpp_tutorials/talker

查看得出当前`talker`占用进程为:18666

查看此程序线程如下:

test@test:~$ top -Hp 18666

top - 16:10:40 up 3 days,  7:45,  1 user,  load average: 1.28, 1.53, 1.87
Threads:   5 total,   0 running,   5 sleeping,   0 stopped,   0 zombie
%Cpu(s): 24.2 us, 10.0 sy,  1.0 ni, 64.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16048740 total,  1877016 free, 10243696 used,  3928028 buff/cache
KiB Swap:   999420 total,   356972 free,   642448 used.  4216300 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                                                                                                                          
18666 test      20   0  334212  10204   9308 S  0.0  0.1   0:00.24 talker                                                                                                                                           
18677 test      20   0  334212  10204   9308 S  0.0  0.1   0:00.06 talker                                                                                                                                           
18678 test      20   0  334212  10204   9308 S  0.0  0.1   0:00.02 talker                                                                                                                                           
18679 test      20   0  334212  10204   9308 S  0.0  0.1   0:00.08 talker                                                                                                                                           
18684 test      20   0  334212  10204   9308 S  0.0  0.1   0:00.03 talker  

假设当前线程中`18677`占用CPU较高,可使用gstack查看此线程堆栈:

test@test:~$ sudo gstack 18677
Thread 1 (Thread 0x7f2fc158f700 (LWP 12194)):
#0  0x00007f2fc68c2b13 in epoll_wait () at ../sysdeps/unix/syscall-template.S:84
#1  0x00007f2fc78667e7 in ros::poll_sockets(int, pollfd*, unsigned long, int) () from /opt/ros/kinetic/lib/libroscpp.so
#2  0x00007f2fc78efdb9 in ros::PollSet::update(int) () from /opt/ros/kinetic/lib/libroscpp.so
#3  0x00007f2fc7875825 in ros::PollManager::threadFunc() () from /opt/ros/kinetic/lib/libroscpp.so
#4  0x00007f2fc5f7b5d5 in ?? () from /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.58.0
#5  0x00007f2fc5b4c6ba in start_thread (arg=0x7f2fc158f700) at pthread_create.c:333
#6  0x00007f2fc68c251d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

查看此线程堆栈可知,CPU占用是由ros::poll_sockets导致,这样就可以根据此信息锁定函数并进行对应修改。

如果有其他方便方式查看运行中程序CPU占用较高进行排查的方法,欢迎分享~

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值