gdb、strace、pmap、perf等跟踪调试工具使用介绍

gdb调试跟踪

一、命令介绍

命令

命令缩写

命令说明

list

l

显示多行源代码

break

b

设置断点,程序运行到断点的位置会停下来

info

i

描述程序的状态

run

r

开始运行程序

display

disp

跟踪查看某个变量,每次停下来都显示它的值

step

s

执行下一条语句,如果该语句为函数调用,则进入函数执行其中的第一条语句

next

n

执行下一条语句,如果该语句为函数调用,不会进入函数内部执行(即不会一步步地调试函数内部语句)

print

p

打印内部变量值

continue

c

继续程序的运行,直到遇到下一个断点

set var name=v

 

设置变量的值

start

st

开始执行程序,在main函数的第一条语句前面停下来

file

 

装入需要调试的程序

kill

k

终止正在调试的程序

watch

 

监视变量值的变化

backtrace

bt

产看函数调用信息(堆栈)

frame

f

查看栈帧

quit

q

退出GDB环境

 

1、设置断点(b)

break 函数名

break 行号

break 文件名:函数名

break 文件名:行号

break +偏移量

break -偏移量

break *地址

 

break可简写成b

2、查看断点(i b)

info break

可简写成i b

3、删除断点(d ..)

delete <断点id>:删除指定断点

delete:删除所有断点

clear

clear 函数名

clear 行号

clear 文件名:行号

clear 文件名:函数名

4、断点添加条件

break 断点 if 条件;比如break sum if value==9,当输入的value为9的时候才会断住。

condition 断点编号:给指定断点删除触发条件

condition 断点编号 条件:给指定断点添加触发条件

5、断点通过disable/enable临时停用启用

disable

disable 断点编号

disable display 显示编号

disable mem 内存区域

 

enable

enable 断点编号

enable once 断点编号:该断点只启用一次,程序运行到该断点并暂停后,该断点即被禁用。

enable delete 断点编号

enable display 显示编号

enable mem 内存区域

6、运行(r)

run运行,如有参数则跟在run命令后,如run 9

如果需要断点在main处,则直接start即可

7、显示栈帧、局部变量(bt)

通过bt可以显示栈帧,bt full可以显示局部变量。

 

bt

bt full:不仅显示backtrace,还显示局部变量

bt N:显示开头N个栈帧

bt full N

8、单步执行(n|s)

单步执行有两个命令next和step,两者的区别是next遇到函数不会进入函数内部,step会执行到函数内部

如果需要逐条汇编指令执行,可以分别使用nexti和stepi。

 

9、继续执行(c)

 调试时,使用continue命令继续执行程序。程序遇到断电后再次暂停执行;如果没有断点,就会一直执行到结束。

continue:继续执行

continue 次数:继续执行一定次数

要想找到变量在何处被改变,可以使用watch命令设置监视点watchpoint。

watch <表达式>:表达式发生变化时暂停运行

awatch <表达式>:表达式被访问、改变是暂停执行

rwatch <表达式>:表达式被访问时暂停执行

 

10、监视点(w)

要想找到变量在何处被改变,可以使用watch命令设置监视点watchpoint。

watch <表达式>:表达式发生变化时暂停运行

awatch <表达式>:表达式被访问、改变是暂停执行

rwatch <表达式>:表达式被访问时暂停执行

11、生成内核转储文件

通过“generate-core-file”生成core.xxxx转储文件。

 

然后gdb ./main ./core.xxxx查看恢复的现场。

12、attach到进程 

二、跟踪mysqld

1、查看mysqld进程pid

 

2、运行gdb

[root@mysqldb ~]# gdb -p 7806

GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-114.el7

Copyright (C) 2013 Free Software Foundation, Inc.

License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software: you are free to change and redistribute it.

There is NO WARRANTY, to the extent permitted by law.  Type "show copying"

and "show warranty" for details.

This GDB was configured as "x86_64-redhat-linux-gnu".

For bug reporting instructions, please see:

<http://www.gnu.org/software/gdb/bugs/>.

Attaching to process 7806

Reading symbols from /usr/local/mysql-5.7.26-linux-glibc2.12-x86_64/bin/mysqld...done.

Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done.

[New LWP 7835]

[New LWP 7834]

[New LWP 7833]

[New LWP 7832]

[New LWP 7831]

[New LWP 7830]

[New LWP 7829]

[New LWP 7828]

[New LWP 7827]

[New LWP 7826]

[New LWP 7825]

[New LWP 7824]

[New LWP 7823]

[New LWP 7822]

[New LWP 7821]

[New LWP 7818]

[New LWP 7817]

[New LWP 7816]

[New LWP 7815]

[New LWP 7814]

[New LWP 7813]

[New LWP 7812]

[New LWP 7811]

[New LWP 7810]

[New LWP 7809]

[New LWP 7808]

[New LWP 7807]

[Thread debugging using libthread_db enabled]

Using host libthread_db library "/lib64/libthread_db.so.1".

Loaded symbols for /lib64/libpthread.so.0

Reading symbols from /lib64/libaio.so.1...Reading symbols from /lib64/libaio.so.1...(no debugging symbols found)...done.

(no debugging symbols found)...done.

Loaded symbols for /lib64/libaio.so.1

Reading symbols from /lib64/libnuma.so.1...Reading symbols from /lib64/libnuma.so.1...(no debugging symbols found)...done.

(no debugging symbols found)...done.

Loaded symbols for /lib64/libnuma.so.1

Reading symbols from /lib64/libcrypt.so.1...(no debugging symbols found)...done.

Loaded symbols for /lib64/libcrypt.so.1

Reading symbols from /lib64/libdl.so.2...(no debugging symbols found)...done.

Loaded symbols for /lib64/libdl.so.2

Reading symbols from /lib64/librt.so.1...(no debugging symbols found)...done.

Loaded symbols for /lib64/librt.so.1

Reading symbols from /lib64/libstdc++.so.6...(no debugging symbols found)...done.

Loaded symbols for /lib64/libstdc++.so.6

Reading symbols from /lib64/libm.so.6...(no debugging symbols found)...done.

Loaded symbols for /lib64/libm.so.6

Reading symbols from /lib64/libgcc_s.so.1...(no debugging symbols found)...done.

Loaded symbols for /lib64/libgcc_s.so.1

Reading symbols from /lib64/libc.so.6...(no debugging symbols found)...done.

Loaded symbols for /lib64/libc.so.6

Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.

Loaded symbols for /lib64/ld-linux-x86-64.so.2

Reading symbols from /lib64/libfreebl3.so...Reading symbols from /lib64/libfreebl3.so...(no debugging symbols found)...done.

(no debugging symbols found)...done.

Loaded symbols for /lib64/libfreebl3.so

Reading symbols from /lib64/libnss_files.so.2...(no debugging symbols found)...done.

Loaded symbols for /lib64/libnss_files.so.2

Reading symbols from /usr/local/mysql57/lib/plugin/semisync_master.so...done.

Loaded symbols for /usr/local/mysql57/lib/plugin/semisync_master.so

Reading symbols from /usr/local/mysql57/lib/plugin/semisync_slave.so...done.

Loaded symbols for /usr/local/mysql57/lib/plugin/semisync_slave.so

0x00007f449b97cbed in poll () from /lib64/libc.so.6

Missing separate debuginfos, use: debuginfo-install glibc-2.17-292.el7.x86_64 libaio-0.3.109-13.el7.x86_64 libgcc-4.8.5-39.el7.x86_64 libstdc++-4.8.5-39.el7.x86_64 nss-softokn-freebl-3.36.0-5.el7_5.x86_64 numactl-libs-2.0.9-7.el7.x86_64

(gdb)

3、设置断点

# 此mysql源码sql_insert.cc423行的函数Sql_cmd_insert::mysql_insert

 

(gdb)  b Sql_cmd_insert::mysql_insert

Breakpoint 1 at 0xea1035: file /export/home/pb2/build/sb_0-33648028-1555164244.06/mysql-5.7.26/sql/sql_insert.cc, line 422.

4、另起一个session2登录

在另一个session2中登录数据库,发现无法登录,hung住了,在gdb中执行next(执行下一步代码),可以看到在socket_connection.cc源码第859行无法继续,代码大致是说要获取系统的socket,还有一些监听信息,由于太多了,直接在gdb中执行continue(到下一个可执行的代码),此时session2已经登录成功。

 

在session2执行select等非insert操作一切是正常的。

5、session2执行insert

如果执行insert,则会话又被hung了。可以单步输入n结合bt,查看具体执行过程

 

pmap

pmap内存分析工具,可以查看进程的内存映像信息。常用来检查是否存在内存泄露 问题

 

-x   extended       Show the extended format. 显示扩展格式

-d  device         Show the deviceformat.   显示设备格式

-q   quiet          Do not display some header/footerlines. 不显示头尾行

 -V   show version   Displays version of program. 显示版本

 

 

mapped 表示该进程映射的虚拟地址空间大小,也就是该进程预先分配的虚拟内存大小,即ps出的vsz

writeable/private  表示进程所占用的私有地址空间大小,也就是该进程实际使用的内存大小     

shared 表示进程和其他进程共享的内存大小

 

 

内存泄露检测方法:

A)VIRT/VSZ或者writeable/private (pmap –d输出)如果在做重复的操作过程中一直保持稳定增长,那么一定有内存泄露。

B) RSS只能作为参考,不能用来确定是否有内存泄露。

 

while true; do pmap -d 4027 | tail -1; sleep 2; done

pstack

pstack用来跟踪进程栈,这个命令在排查进程问题时非常有用,比如我们发现一个服务一直处于work状态(如假死状态,好似死循环),使用这个命令就能轻松定位问题所在;可以在一段时间内,多执行几次pstack,若发现代码栈总是停在同一个位置,那个位置就需要重点关注,很可能就是出问题的地方;

pt-pmp

pt-pmp可以对生成的pstack输出文件进行排序分析,也可以直接对进程进行堆栈排序分析。

pt-pmp对堆栈信息排序:

pt-pmp pstack.info | less

也可以直接执行pt-pmp:

pt-pmp --pid 4522

 

strace

strace常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间

 

strace可以跟踪正在运行的进程,或可以加执行命令进行跟踪。

 

选项

说明

-f

跟踪目标进程,以及目标进程创建的所有子进程(fork, vfork and clone)

-ff

结果-o一起使用,把strace输出到filename.pid,pid线程ID

-o

 把strace的输出单独写到指定的文件

-F

已降级参数,功能同-f

-p

指定要跟踪的进程pid, 要同时跟踪多个pid, 重复多次-p选项即可

-s

当系统调用的某个参数是字符串时,最多输出指定长度的内容,默认是32个字节

-T

显示每次系统调用所花费的时间

-tt

在每行输出的前面,显示毫秒级别的时间

-v

 对于某些相关调用,把完整的环境变量,文件stat结构等打出来

-e

控制要跟踪的事件和跟踪行为,比如指定要跟踪的系统调用名称

 

-e trace=file     跟踪和文件访问相关的调用(参数中有文件名)
-e trace=process  和进程管理相关的调用,比如fork/exec/exit_group
-e trace=network  和网络通信相关的调用,比如socket/sendto/connect
-e trace=signal    信号发送和处理相关,比如kill/sigaction
-e trace=desc  和文件描述符相关,比如write/read/select/epoll等
-e trace=ipc 进程见同学相关,比如shmget等

 

跟踪nginx访问了哪些文件

strace -tt -T -f -e trace=file -o /data/log/strace.log -s 1024 ./nginx

 

MySQL查看执行语句

mysqld_pid=4027

strace -f -F -ff -o mysqld-strace -s 1024 -p $mysqld_pid  #此会每个线程生成一个文件,文件名后缀为OS Thread ID.

ls mysqld-strace.* |xargs grep -ni "select"

 

 

perf

perf是Linux下的一款性能分析工具,能够进行函数级与指令级的热点查找。

Linux性能计数器是一个新的基于内核的子系统,它提供一个性能分析框架,比如硬件(CPU、PMU(Performance Monitoring Unit))功能和软件(软件计数器、tracepoint)功能。

通过perf,应用程序可以利用PMU、tracepoint和内核中的计数器来进行性能统计。它不但可以分析制定应用程序的性能问题(per thread),也可以用来分析内核的性能问题,当然也可以同时分析应用程序和内核,从而全面理解应用程序中的性能瓶颈。

使用perf,可以分析程序运行期间发生的硬件事件,比如instructions retired、processor clock cycles等;也可以分析软件时间,比如page fault和进程切换。

 

1、命令介绍

1

annotate

2

archive

根据数据文件记录的build-id,将所有被采样到的elf文件打包。利用此压缩包,可以再任何机器上分析数据文件中记录的采样数据。

3

bench

perf中内置的benchmark,目前包括两套针对调度器和内存管理子系统的benchmark。

4

buildid-cache

管理perf的buildid缓存,每个elf文件都有一个独一无二的buildid。buildid被perf用来关联性能数据与elf文件。

5

buildid-list

列出数据文件中记录的所有buildid。

6

diff

对比两个数据文件的差异。能够给出每个符号(函数)在热点分析上的具体差异。

7

evlist

列出数据文件perf.data中所有性能事件。

8

inject

该工具读取perf record工具记录的事件流,并将其定向到标准输出。在被分析代码中的任何一点,都可以向事件流中注入其它事件。

9

kmem

针对内核内存(slab)子系统进行追踪测量的工具

10

kvm

用来追踪测试运行在KVM虚拟机上的Guest OS。

11

list

列出当前系统支持的所有性能事件。包括硬件性能事件、软件性能事件以及检查点。

12

lock

分析内核中的锁信息,包括锁的争用情况,等待延迟等。

13

mem

内存存取情况

14

record

收集采样信息,并将其记录在数据文件中。随后可通过其它工具对数据文件进行分析。

15

report

读取perf record创建的数据文件,并给出热点分析结果。

16

sched

针对调度器子系统的分析工具。

17

script

执行perlpython写的功能扩展脚本、生成脚本框架、读取数据文件中的数据信息等。

18

stat

执行某个命令,收集特定进程的性能概况,包括CPICache丢失率等。

19

test

perf对当前软硬件平台进行健全性测试,可用此工具测试当前的软硬件平台是否能支持perf的所有功能。

20

timechart

针对测试期间系统行为进行可视化的工具

21

top

类似于linuxtop命令,对系统性能进行实时分析。

22

trace

关于syscall的工具。

23

probe

用于定义动态检查点。

 

2、使用示例一

2.1 采集mysqld进程60秒的性能数据

sudo perf record -a -F 99 -g -p $(pgrep -x mysqld) -- sleep 60

Warning:

PID/TID switch overriding SYSTEM

[ perf record: Woken up 1 times to write data ]

[ perf record: Captured and wrote 0.081 MB perf.data ]

 

参数:-F 99Hz采集,它的执行频率是 99Hz(每秒99次)

 

2.2 持续采集mysqld性能数据,直到ctrl+c取消

sudo perf record -a -F 99 -g -p $(pgrep -x mysqld)

 

2.3 数据加工

sudo perf script > perf.script

2.4 生成火焰图

安装FlameGraph(该工具也可以分析如dtrace、gdb等等生成的trace)

git clone https://github.com/brendangregg/FlameGraph.git 

 

./FlameGraph/stackcollapse-perf.pl perf.script | ./FlameGraph/flamegraph.pl > flamegraph.svg

 

3、使用示例二(通过top来分析性能消耗)

perf top -p `pidof mysqld`

 

第一列:符号引发的性能事件的比例,默认指占用的cpu周期比例。

第二列:符号所在的DSO(Dynamic Shared Object),可以是应用程序、内核、动态链接库、模块。

第三列:DSO的类型。[.]表示此符号属于用户态的ELF文件,包括可执行文件与动态链接库)。[k]表述此符号属于内核或模块。

第四列:符号名。有些符号不能解析为函数名,只能用地址表示。

 

其他

SystemTap、dtrace等工具相对使用较复杂,此不介绍

pldd :可查看程序依赖的共享库信息

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值