3 SystemTap 脚本的各大组件

SystemTap 脚本语言里的主要结构是定义探针(probe) 。探针将抽象事件与语句块或探针处理函数联系到一起,事件发生时,将执行这些语句块或探针处理函数。

下述例子展示了如何利用两个探针来跟踪函数的进入和退出。

probe kernel.function("sys_mkdir").call { log ("enter") }

probe kernel.function("sys_mkdir").return { log ("exit") }

可以使用列表选项(-l) 来查看内核所有可探测函数(probe-able functions) ,例如:

# stap -l 'kernel.function("*")' | sort

3.1 探针定义

探针定义的一般语法形式如下:

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

探针里具体定义的事件称为探测点 (probe points) 。转换器(译者注:转换器是systemTap 工具的一部分,它负责将systemTap脚本转换成C 代码的工作)已预先定义了大量的探测点,同时tapset 脚本可能使用探针别名来定义另一些探测点。Stapprobes(5) 用户手册列出了所有可供使用的探测点。

探针处理函数总是根据事件的上下文来解释执行。那些与内核代码关联的事件,它的上下文包括内核源代码那里定义的变量。SystemTap 脚本使用一种以$ 字符开头的变量,称为目标变量。只有内核代码编译时没有打开优化选项,内核镜像才会保存该目标变量引用的内存地址,这样目标变量才能被访问。这与调试器调试被优化的代码一样,同受此限制。

3.2 探针别名

探针别名的一般语法形式如下:

probe <alias> = <probepoint> { <prologue_stmts> }

probe <alias> += <probepoint> { <epilogue_stmts> }

我们可以使用探针别名的方法来定义新的探测点。在形式上,探测点别名和探针定义很相似,它只在现有探测点之上定义另一新的探测点名字作为它的别名,并没有激活探针。新的探针别名可以定义在一个或多个现有探针别名之上,并且多个探针别名可以定义在同一探针(别名)之上。请看下面例子:

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

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

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

SystemTap 脚本的探针别名分为两种,序式(prologue style) 别名和跋式(epilogue style) 别名,定义时分别由等号(=) 和“+=”符号表示。

由新探测点别名定义的探针,它利用探针别名定义时预先定义的处理函数来创建真正的探针。

这种预先定义的方式有多种好处。它允许在将控制权交到由用户定义的探针处理函数前,根据别名定义时语句块来预先处理探针的上下文。它的用处多种多样,演示如下:

# 忽略当前探针,直到满足给定的条件:

if ($flag1 != $flag2) next

# 为使用该别名的探针提供有用的值

name = "foo"

# 将目标变量的值提取到一般的局部变量

var = $var

3.2 序式别名(= )

序式别名定义时后面紧跟着的语句块将隐式地添加到使用该别名的探针,作为探针处理函数的序幕。请看下述例子:

# 定义新的探测点syscall.read ,它扩展为

# kernel.function("sys_read") 探测点,而给定的语句将作为探针处函

# 数的序幕。

probe syscall.read = kernel.function("sys_read") {

fildes = $fd

}

3.2.2 跋式别名(+= )

跋式别名定义时后面紧跟着的语句块将隐式地添加到任何引用该别名的探针,并作为此探针处函数的 跋。通常它的语句块内不会定义新的变量(因为后面没有代码使用它),但可以针对跋式别名语句块内设置的变量或探针内用户定义的变量采取相应的动作。请看下面例子:

# 定义一个新的探测点,给定的语句作为 跋

probe syscall.read += kernel.function("sys_read") {

if (traceme) println ("tracing me")

}

3.2.3 探针别名用法

探针别名用法与其它内置的探针类型用法一致,只需将之命名(naming) 即可:

probe syscall.read {

printf("reading fd=%d/n", fildes)

}

3.2.4 空置的别名变量(Unused alias variables)

空置别名变量是定义在探针别名内的变量,通常是由var = $var 这类赋值语句来定义的,但事实上它没有被该别名实例化的探针上使用。这些变量被白白丢弃了。

3.3 变量

变量和函数标识符是由字母或数字组成的字符串,同时包括下划线(_) 和美元符号($) ,但不能以纯数字字母开始。默认情况下,变量只是探针或函数语句块内的局部变量,因此它的使用范围和生命周期仅局限于具体的探针和函数调用。关联数组内可以储存字符串和整数,同时字符串或整数元组可作为关联数组的键值。数组必须定义为全局变量,不允许定义局部数组变量。

换转器对各个标识符都进行类型推导,包括数组下标,函数实参。与标识符类型不相容的使用均导致错误。

变量一旦定义为全局变量,所有的探针和SystemTap 会话里其它实例共享该全局变量。所有全局变量都在同一命名空间下,无论全局变量定义在那个文件。由于实际并发的限制,如多个探针处理函数,探针在运会时对使用的每个全局变量会自动加上读或写锁。全局变量声明可以在代码块内,亦可在脚本文件最外层结构的任何地方。那些仅定义,但没有读取的全局变量,会话结束时会自动输出它的值。下述的声明表明var1 和var2 是全局变量。转换器会为它们进行类型推导,如果变量用作数组,换转器会进一步推导它键值的类型。

global var1[=<value>], var2[=<value>]

3.4 辅助函数

辅助函数的一般语法形式是:

function <name>[:<type>] ( <arg1>[:<type>], ... ) { <stmts> }

SystemTap 脚本可定义子例程来分解公共的工作。函数可以有任意多个标量参数,但必须返回单标量值。这里标量是指整数或字符串。更多关于标量的信息,请参阅3.3 节和5.3 节。下述是一个函数声明的例子:

function thisfn (arg1, arg2) {

return arg1 + arg2

}

注意,函数不需要声明它的类型(译者注:函数类型即函数的返回类型),它是由转换器推导出来的。如果需要,函数定义时可以显式声明它的返回值类型,或参数类型,或者两者。这对emdedded-C 函数非常有用。在下述例子中,类型推导引擎只需推断arg2 参数的类型,为string 。

function thatfn:string(arg1:long, arg2) {

return sprintf("%d%s", arg1, arg2)

}

数函可以调用其它函数,可递归调用自己,但有一限制就是不能超过最大的内嵌调用层次,详情请参阅1.6 节。

3.5 Embedded C

SystemTap 支持guru 模式, 脚本安全特性,诸如代码或数据内存引用保护,统统失效。可在stap 命令上使用 ''-g'' 选项来打开Guru 模式。在guru 模式下,转换器接受脚本文件由``%{'' 和``%}'' 标记对包含的embedded 代码。Embedded 代码不经分析 逐字翻译并生成 C 代码。在脚本的最外层, guru 模式下可以使用 #include 指令,或任何方便其它 embedded 代码使用的辅助定义。

3.6 Embedded C 函数

Embedded C 函数的一般语法形式:

function <name>:<type> ( <arg1>:<type>, ... ) %{ <C_stmts> %}

函数体允许是embedded 代码。若如此,脚本语言主体全部由%{ 和%} 标记包含的C 代码片段所取代。分析器(parser) 不会让这些C 代码胡作非为,它只能做析器视为合理和安全的事情。

在并发,资料消耗和运行时限制方面,SystemTap 语言代码仍然存在大量非文档化但复杂的安全约束。但这些约束不能应用于embedded C 代码,编写这类代码要小心,因为它会原封不动地翻译成C 代码。解引指针时必须特别小心,使用kread() 宏来解引指针仍然会造成潜在非法或危险的可能。如果不能确定,宁可谨慎并使用kread() 。Embedded C 生成的代码所使用的安全机制有多种,其中之一是使用kread() 宏。它保护指针访问,以避免系统 崩溃 ( crash) 。

例如,在embedded C 中访问指针链name = skb->dev->name ,所用代码如下:

struct net_device *dev;

char *name;

dev = kread(&(skb->dev));

name = kread(&(dev->name));

函数使用THIS 宏来访问输入和输出值的内存位置。如下例所示:

function add_one (val) %{

THIS->__retvalue = THIS->val + 1;

%}

function add_one_str (val) %{

strlcpy (THIS->__retvalue, THIS->val, MAXSTRINGLEN);

strlcat (THIS->__retvalue, "one", MAXSTRINGLEN);

%}

为确保这种方法能工作,转换器必须能够从函数的调用来推导它的参数和返回值类型。你可以查核一般脚本语言函数生成的 C 代码,来编写兼容的 embedded-C 代码。注意,所有 SystemTap 函数和探针均运行在中断禁用情况下,因此你不能在 embedded C 代码里调用会睡眠的函数

《System语言详解》——3. SystemTap脚本的各大组件相关推荐

  1. Drools 规则语言详解(上)

    http://www.blogjava.net/guangnian0412/archive/2006/06/09/51574.html http://www.blogjava.net/guangnia ...

  2. system()函数详解

    windows下system () 函数详解 windows操作系统下system () 函数详解(主要是在C语言中的应用) 函数名: system 功 能: 发出一个DOS命令 用 法: int s ...

  3. 有向图邻接矩阵c语言编程,邻接矩阵有向图(一)之 C语言详解

    本章介绍邻接矩阵有向图.在"图的理论基础"中已经对图进行了理论介绍,这里就不再对图的概念进行重复说明了.和以往一样,本文会先给出C语言的实现:后续再分别给出C++和Java版本的实 ...

  4. 邻接矩阵用c语言,邻接矩阵无向图(一)之 C语言详解

    本章介绍邻接矩阵无向图.在"图的理论基础"中已经对图进行了理论介绍,这里就不再对图的概念进行重复说明了.和以往一样,本文会先给出C语言的实现:后续再分别给出C++和Java版本的实 ...

  5. 克鲁斯卡尔算法c语言,Kruskal算法(一)之 C语言详解

    最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树. 例如,对于如上图G4所示的连通网可以有多棵权值总和 ...

  6. c++指针详解_c语言详解sizeof

    一.sizeof的概念 sizeof是C语言的一种单目操作符,如C语言的其他操作符++.--等. 它并不是函数. sizeof操作符以字节形式给出了其操作数的存储大小. 操作数可以是一个表达式或括在括 ...

  7. System.load 和 System.loadLibrary详解

    System.load 和 System.loadLibrary详解 1.它们都可以用来装载库文件,不论是JNI库文件还是非JNI库文件.在任何本地方法被调用之前必须先用这个两个方法之一把相应的JNI ...

  8. 排座系统c语言,2008noip排座位C语言详解.doc

    2008noip排座位C语言详解 2008noip排座位C语言详解 2.排座椅 (seat.pas/c/cpp)D对同学上课时会交头接耳.同学们在教室中坐成了M行N列,坐在第i行第j列 的同学的位置是 ...

  9. 如何用c语言编写stm32的程序吗,STM32入门C语言详解

    <STM32入门C语言详解>由会员分享,可在线阅读,更多相关<STM32入门C语言详解(6页珍藏版)>请在人人文库网上搜索. 1.最新 料推荐阅读 flash : 芯片内部存储 ...

  10. 顺序栈基本操作(入栈和出栈)C语言详解

    #include <stdio.h> #include <stdlib.h> /*顺序栈基本操作(入栈和出栈)C语言详解栈的具体实现(1)顺序栈(2)链栈栈的应用(1)回退 ( ...

最新文章

  1. 在开发的过程如何使用源码
  2. DATAGRID学习
  3. Android studio使用心得(二)— 打包签名apk发布
  4. 迭代器模式源码解析(jdk+mybatis)
  5. 蚂蚁海图切片工具linux版本,Web海图服务软件 - 海图在线
  6. java json对象 输出_拼json字符串输出java对象
  7. ios html清除缓存图片,iOS,如何清理缓存的图片
  8. ElasticSearch filter查询
  9. laravel api_如何在现有的Laravel应用中获取即时GraphQL API
  10. 如何用iOS工程生成iOS模拟器包
  11. 从skyeye学习arm(文件系统篇)
  12. Windows下 ffmpeg + labelImg 提取视频帧 得到图片集 并 标注图片 来 构造数据集
  13. 如何增加虚拟机ubuntu的硬盘
  14. 伪静态在webconfig中配置
  15. 对比iOS中的四种数据存储
  16. apache 的batik生成svg文件和通过swing界面查看效果
  17. 判断文章内容重复率的算法实现
  18. 拔掉MacBookPro,用8GB树莓派4工作一天,体验原来是这样的
  19. java Complex 类
  20. 7-1 查找书籍 (20 分)给定n本书的名称和定价,本题要求编写程序,查找并输出其中定价最高和最低的书的名称和定价。输入格式:输入第一行给出正整数n(<10),随后给出n本书的信息

热门文章

  1. mysql workbench 建表时PK, NN, UQ, BIN, UN, ZF, AI
  2. 工作是工作,爱好是爱好,理想是另外一回事
  3. [macOS] git忽略所有的.DS_Store文件
  4. 手机圈老兵任伟光加盟联想
  5. java io 字符流操作工具类
  6. iOS第三方开源库的吐槽和备忘
  7. PostgreSQL导出导入schema相关
  8. Spring with multiple transaction managers
  9. WinCE6.0下TCPMP的BenchMark汇总
  10. 开发者论坛一周精粹(第六十三期) WHM自动脚本修复ssh问题