SystemTap工具的使用基础

SystemTap工具的使用基础,第1张

查看当前内核版本是哪一个,然后使用

找到内核构建的详细信息,然后去对应发布网站上找kernel-debuginfo和kernel-debuginfo-common包。

完成安装后可以通过下面命令测试systemtap

进行测试,看看systemtap有无安装成功。

下面命令演示查看__lookup_hash()函数返回时刻可以查看到的变量

在上表中显示了lookup_hash在文件中的行号,显示了名为$return 的变量,其实这个return变量就是systemtap表示函数返回值的。而$name,$base,$flag我们对着linux源码看发现这是__lookup_hash的三个入参。

下面命令可以查看__lookup_hash函数入口可以查看的变量

也可以通过statement方式查看内核符号表里有的__lookup_hash相关的行

如果查找的内核函数位于某个模块里可以使用下面命令:

通过下面命令可以查看到某个正在运行的进程的函数

上例中看到找到了syscall.Mount函数,并且把它的所有参数和参数类型都打印了出来。

后面可以在stap脚本中,这个函数的上下文里直接使用这些参数,例如通过$source可以访问到参数source

systemtap支持print()和printf()函数,其中printf使用语法和c语言一致。支持%s,%d,%x格式

在systemtap里凡是以$开头的变量都是目标变量,如果目标变量结构体指针或者结构体对象,那么可以使用->直接访问其成员。例如上例中:

常规情况下,printf()打印target变量时刻,只打印其值。如果需要将其成员(指针类型的target需要将其指向的对象的成员展开)可以在target变量后面加$的方式例如:

一般情况下对struct的展开只会到成员值一级,如果相对成员内部继续展开可以在目标变量后面跟$$

在systemtap中支持逻辑if语句格式为:

逻辑语句支持以下比较

==,!=,>=,>,<,<=

上述例子对ls -l下的xmalloc进行堆栈回溯:

-d 可执行文件名

--ldd 指明共享库

-c “ls -l” 执行的子进程体

下面例子将打印__lookup_hash中return返回dentry*里inode指向的i_ino子成员

这一例子中-o zxy.txt的意思就是将结果写入文件zxy.txt中(默认输出到控制台)

下面例子将在内核中使用强制类型转换

这里解释一下,内核中方法强制转换

在用systemtap跟踪内核时使用堆栈打印命令,常常打印不出来另外模块的函数,这是因为这些模块没有被加载。可以在systemtap启动命令使用--all-modules 方法强制将所有模块符号加载起来。

下面例子对用golang写的dockerd进程syscall.Mount调用入口时刻打印syscall.Mount()函数的参数

source的string字段内容

下面例子打印golang写的dockerd进程xxx.Get函数返回时刻的参数情况

}

systemtap对golang支持不够完美,用户需要自己解析基本结构例如golang的string,array和slice这些都需要用户自己解析。string被systemtap识别为struct string,此结构systemtap可以识别的定义可以简化为:

需要注意的是 通过systemtap打印golang string的string->str会多打很多字符,因为string成员str并非按照c语言定义的字符串以表示字符串结束,我们只能结合string的字段len来获取精确的字符串内容

slice完全不被systemtap识别,我们可以将systemtap可以识别的slice简化为此种定义:

其中array就是指向slice存储单元的首地址。

要是我们想获取helo=[]string{“hello”,”world”}这样的字符串slice的内容可以通过systemtap提供的@cast(addr,”type”,”file”)函数将某个地址强转为file中定义的type结构。具体来说可以如下做获取hello的内容

其实下面要说的没多少硬货,算是个自己这些日子使用春哥写的那几个systemtap脚本调优的经验总结吧。

一、systemtap安装

因为一直在ubuntu上使用,所以安装很简单 sudo apt-get install systemtap,源码安装的话请参考这篇文章:http://www.cnblogs.com/hazir/p/systemtap_introduction.html 中的方法一。

二、内核调试信息

不用跟踪内核态性能大概也不需要,不过保不齐会用到所以我也把内核调试信息搞上了。对于ubuntu这种发行版内核来说好处是官方已经提供了(URL:http://ddebs.ubuntu.com/pool/main/l/linux/),根据自己的内核(uname -a 查询)挑选版本。 如我的是Linux ubuntu 3.13.0-32-generic 那么对应的就是:linux-image-3.13.0-32-generic-dbgsym_3.13.0-32.57_amd64.ddeb。

下载后用 dpkg -i linux-image-3.13.0-32-generic-dbgsym_3.13.0-32.57_amd64.ddeb 安装。

三、Hello Systemtap!

上面这些完成以后可以使用命令:sudo stap -ve 'probe begin { log("hello Systemtap!") exit() }' 来测试是否安装成功。如果成功的话会有类似下面的输出:

春哥的nginx <wbr>systemtap调试脚本简单介绍

四、nginx-systemtap-toolkit

进入正题,这个就是主要介绍的章亦春大神写的systemtap nginx调试的系列脚本了(URL:Github地址),提供了活动请求的查询、ngx_lua模块的当前lua堆栈查看、pcre模式串/运行时间分析、C堆栈采样等等炸裂功能。

首先介绍下C堆栈采样这个脚本,结合Brendan Gregg大神写的FlameGraph tools(URL:https://github.com/brendangregg/FlameGraph),可以画出功能实用、看着酷炫的火焰图。如图:春哥的nginx <wbr>systemtap调试脚本简单介绍

这个东西的原理就是在程序运行的时候每隔一定的时间对指定进程的C堆栈进行采样,将当前各栈帧的函数名保存起来。因为采样时间是恒定的,所以最后的结果上如果一个函数占用cpu时间越长,那么得到的采样次数也就越多,最后反映到火焰图上的横轴长度就越长。另外颜色深浅其实没什么含义,只是方便查看。

使用方法:

1、首先确定编译的代码要带有调试i信息,以便调试脚本可以获得具体的代码信息。如nginx就要加上--with-debug开关。

2、其次要调优的进程已经启动,并且获得其pid,对于nginx这种多进程的程序,需要找到一个worker进程的pid,所以如果是开发环境调优的话,可以考虑使用单进程跑nginx。

3、命令sudo ./nginx-systemtap-toolkit/sample-bt -p 1147 -u -t 20 >trace.txt

其中-p 指定进程的pid

-u 追踪用户态的调用堆栈(也可以使用-k追踪程序运行期间在内核态的堆栈)

-t 脚本的运行时间,达到时间之后脚本自动停止,将堆栈信息输出,单位为秒

启动后会有类似的信息:

WARNING: Tracing 1147 (/home/kawaru/nginx/sbin/nginx) in user-space only...

提示已经开始跟踪,这是可以用ab等等东西打点流量,等20秒之后会显示:

WARNING: Time's up. Quitting now...(it may take a while)

您好,内存去哪了SystemTap余峰?答案是:内存去哪了SystemTap余峰?答案是:内存会被系统调度器分配给不同的进程,以满足这些进程的需求。当内存不够用时,系统会自动释放一些内存,这就是SystemTap余峰的概念。


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/yw/7323943.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-04
下一篇2023-04-04

发表评论

登录后才能评论

评论列表(0条)

    保存