system tap简单使用

来源:互联网 发布:淘宝客软文范例 编辑:程序博客网 时间:2024/06/15 19:00

最近学习system tap的一些使用,虽然目前还是对于linux内核学习还是很菜的菜鸟,作为处女作,希望大家多喷,欢迎交流指错。参考资料来源http://www.sourceware.org/systemtap/documentation.html

systemtap简介

system tap是一种检查内核运行情况的工具,它允许开发者和管理员编写和重新使用简单脚本深入检查一个正在运行的linux系统的活动。可以快速安全地提取、筛选、总结相关活动的数据,来诊断分析linux内核复杂的性能或者函数功能问题。

systemtap脚本的重要思想是指定事件(events系统活动或者内核函数执行),然后当这些事件触发的时候,需要编写对这些事件进行处理的处理程序(handlers)。其实根据这个systemtap的思想,我就先提出自己的一点见解,要指定事件,你要做的就是对内核有一定的了解,这里更多的涉及内核代码层次的了解多一点,针对处理程序,我们要做的更多的是对systemtap脚本的了解,当然针对我们需要查询的数据,你同样需要掌握内核函数的某些参数。总之,你需要学好linux内核,再来用systemtap就能很好的发挥它的功能作用。

这里列举几种事件,函数的调用和退出,计时器到期,整个systemtap会话开始或者停止等等。处理程序就是语言脚本的一系列声明,这些声明的作用就是当事件发生时,处理程序需要做的工作,一般工作包括从事件执行的上下文中提取数据,用处理程序的内部变量存储这些数据,或者打印出这些数据。

 systemtap的工作过程:

1 .将systemtap脚本翻译成C语言

2,用C语言编译器将上述C语言代码编译成一个内核模块

3.当这个模块被加载,通过钩子函数,它会把所有的探测事件

4.当事件被处理器执行,被编译的处理程序就会运行。最终,当会话结束,钩子函数就会分离,模块也会被移除。

 probe definitions

     probe PROBEPOINT [,PROBEPOINT]       { [STMT ...] }

在上述定义中,探测点(PROBEPOINT)是以一种systemtap脚本语法用来指定事件(events)。在翻译器(translator)中定义了几种探测(PROBEPOINT),在tapset库里面用别名(aliases)也定义了其他的一些探测点。当任何有探测点(PROBEPOINT)指定的事件发生时,STMT语句块就会被执行。

根据每个事件的上下文翻译解释探针处理程序。因为事件与内核代码相关,所以这些上下文可能包括在相关内核源代码中定义的变量。这些被称为目标变量(上下文变量)可以作为变量提供给systemtap脚本,但是这些目标变量访问的时候需要加前缀$。当然这些目标变量只有在编译器编译内核的时候没有被优化,而是保存下来才能被访问。

PS:名词解释

Tapset库:类似于C库,systemtap建立了一个脚本库供大家使用,一个”tapset”就是一个为了复用而设计的脚本,通过安装到一个指定的目录下,缺省情况下的目录是/usr/share/systemtap/tapset.大家可以用vi编辑器直接访问某些脚本函数,进一步了解systemtap机制。

别名(aliases):使用别名,可以定义新的探测点(PROBEPOINT)。一个探针别名(alias)与探针定义很相似,而不是在已知的探测点去使探针发生,它是对已存在的探测点以别名的方式定义了一个新的探针点。新定义的探针别名可以适用于一个或多个已存在的探针别名。多个别名可以共享相同的潜在的探测点。举个例子:

probe socket.sendmsg = kernel.function ("sock_sendmsg") { ... }

probe socket.do_write = kernel.function ("do_sock_write") { ...}

probe socket.send = socket.sendmsg, socket.do_write { ... }

 stap命令

stap程序是systemtap工具的前端。它接受systemtap脚本编写的探测指令代码,stap运行过程具体参考下图:

以root命令运行:$sudo stap –ve ‘probe{log(”helloworld”) exit()}’


systemtap脚本运行直到下面某个条件发生时终止:

• 用户使用中断指令CTRL-C.

• 脚本运行到exit() 函数.

•脚本遇到大量的软件错误(soft errors).

•监测命令运行直到stap-C选项发生时推出

Stap命令的某些选项:

-v addverbosity to all passes 打印出所有步骤的冗长信息

-c CMD  start the probes,run CMD,and exit when itfinishes

运行脚本,运行CMD命令,当CMD命令运行结束,整个probe退出

 -e SCRIPT  Run given script

-h 查看stap的使用方法

设置probe的探测点

systemtap支持许多内置事件(events)。安装Systemtap时一起安装上的脚本库(tapset:http://sourceware.org/systemtap/tapsets/)定义了附加的事件。所有的事件都使用统一的点分隔符来命名:

探针类型

说明

begin

在脚本开始时触发

end

在脚本结束时触发

kernel.function("sys_sync")

调用 sys_sync 时触发

kernel.function("sys_sync").call

同上

kernel.function("sys_sync").return

返回 sys_sync 时触发

kernel.syscall.*

进行任何系统调用时触发

kernel.function("*@kernel/fork.c:934")

到达 fork.c 的第 934行时触发

module("ext3").function("ext3_file_write")

调用 ext3 write 函数时触发

timer.jiffies(1000)

每隔 1000 个内核 jiffy触发一次

timer.ms(200).randomize(50)

每隔 200 毫秒触发一次,带有线性分布的随机附加时间

-50 +50


利用tapset库设计处理函数,得到系统的时钟频率:




假如你要追踪一个源文件所有函数的进入和退出,比如内核中的net/socket.c。由于systemtap 为了把目标代码和源代码关联起来,它会去检测内核的编译信息,所以你使用kernel.function探针就很容易实现你的目的。它像一个调试器:只要你能指出它的名字,它就可以探测到。使用kernel.function("*@net/socket.c").call来跟踪进入,kernel.function("*@net/socket.c").return 来探测退出(*是通配符)。你甚至可以具体到行号,就像这样:("*@main.c:200")。当然一旦你确定了探测点位置,那么systemtap脚本的基本框架就成型了。关键字probe引入一个探测点,或者是用逗号分隔的列表(多个探测点),接着就是 { }装入的处理所有列出的探测点的处理函数。

probe kernel.function("*@net/socket.c") { }

probe kernel.function("*@net/socket.c").return { }

探测结果如何输出

systemtap提供了很多例程来打印所需要的信息,包括一些排版。这些函数的返回值可以是string或者是数值型。可以使用c语言型的格式化输出函数printf。用%s输出字符串,%d输出数值。包括换行/nsystemtap提供了一个函数thread_indent(n)来进行缩排。

tid()

当前线程的ID号

pid()

调用当前线程的进程(任务组)ID.

uid()

当前用户的ID

execname()

当前进程名.

cpu()

当前CPU号

gettimeofday_s()

 从新纪元开始计时所达到的秒数

get_cycles()

Snapshot of hardware cycle counter.

pp()

一个描述当前正在被处理探测点的字符串

probefunc()

如果可以获取的话,获取探针所在位置的函数名

$$vars

如果可得的话,获取的是在作用域中的所有局部变量的一个漂亮的输出列表

print_backtrace()

If possible, print a kernel backtrace.

print_ubacktrace()

If possible, print a user-space backtrace.


(这些函数的)返回值可能是字符串或者数字。内建函数print()可以使用任何一种作为其唯一的参数。或者你可以使用C风格的printf()内建函数,其格式参数可以包括表示字符串的%s和表示数字的%dprintf和其他函数接受逗号隔开的多个参数。不要忘了在最后加上"\n"


Tapset库里一个特别便于使用的函数是thread_ident。指定一个缩进值参数,它会在内部为每个线程保存一个缩进计数器,并返回一个带有通用跟踪数据和适量缩进空格的字符串。通用数据包括一个时间戳(从最近的初始缩进开始经过的毫秒数),进程名和线程id。因此它不但可以显示调用了那些函数,还可以显示调用者,以及执行这些函数所用的时间。图3展示了完整的脚本。
下图展示了完整的脚本以及允许情况:






 

 


原创粉丝点击