英文原文:http://sourceware.org/systemtap/langref/SystemTap_overview.html
1 SystemTap概述
1.1 关于本书
本书是SystemTap语言结构和语法的综合参考书,大量引用现有的SystemTap手册和指南文档。读者只要阅读本书,就可从中掌握SysemTap语言的语法和建议性用法。为确保能顺利阅读本书,读者需要了解SystemTap的一般理论和操作。如果你是SystemTap新手,你会发现这是一本优秀的入门者指南。至于详细的tapsets用法,请参阅和本书一起发布的手册。关于完整的SystemTap参考资料集,详见第十章。
1.2 为何使用SystemTap
SystemTap提供了一个基础平台,简化了收集Linux内核运行时信息的工作,便于进一步的分析。这些分析有助于我们识别性能或功能问题的根本原因。SystemTap设计的初衷是使开发人员从原本需要重编译,安装和重启等过程才能收集到这些数据的乏味工作中解脱出来。SystemTap提供一个简单的命令行界面和编写内核测量仪(kernelinstrumentation)的脚本语言。有了SystemTap,开发人员,系统管理员和用户可以很方便地编写脚本来收集和操纵内核数据,这是其它使用标准Linux工具等方法所不能及的。与旧的方法相比,SystemTap的出现是一个显著的进步。
1.3 事件-动作语言
SystemTap语言是一种强类型的,免声明的,面向过程的和起源于dtrace和awk的语言。它将内核中的源代码点和事件关联到处理函数(handler),这些处理函数是异步执行的子例程。探测点(probe)在概念上与GDB调试器上的“断点命令列表”相似类。
SystemTap有两个最外层的结构:探测点和函数。它的语句和表达式使用类C语言的操作符语法和优先级。
1.4 SystemTap脚本范例
下面是一个展示SystemTap基本操作的脚本例子。更多例子,请参阅源代码中的examples/small_demos/目录,SystemTap维基http://sourceware.org/systemtap/wiki/HomePage或SystemTap War Stories http://sourceware.org/systemtap/wiki/WarStories。
1.4.1 SystemTap基础语法和控制结构
下面代码示例演示了SystemTap语法和控制结构。
global odds, evens
probe begin {
# no和ne是局部整型变量
for (i = 0; i< 10; i++) {
if (i % 2)odds [no++] = i
elseevens [ne++] = i
}
delete odds[2]
delete evens[3]
exit()
}
probe end {
foreach (x+ inodds)
printf("odds[%d] = %d", x, odds[x])
foreach (x inevens-)
printf ("evens[%d] = %d", x,evens[x])
}
运行输出:
odds[0] = 1
odds[1] = 3
odds[3] = 7
odds[4] = 9
evens[4] = 8
evens[2] = 4
evens[1] = 2
evens[0] = 0
值得一提的是,所有变量类型是由SystemTap编译器自动推导的,并且所有局部和全局变量在使用前已经初始化了。
1.4.2 0到49之间的质数
function isprime (x) {
if (x < 2)return 0
for (i = 2; i< x; i++) {
if (x % i== 0) return 0
if (i * i> x) break
}
return 1
}
probe begin {
for (i = 0; i< 50; i++)
if (isprime (i)) printf("%d/n", i)
exit()
}
运行输出:
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
1.4.3 递归函数
function fibonacci(i) {
if (i < 1)error ("bad number")
if (i == 1)return 1
if (i == 2)return 2
returnfibonacci (i-1) + fibonacci (i-2)
}
probe begin {
printf("11th fibonacci number: %d", fibonacci (11))
exit ()
}
运行输出:
11th fibonacci number: 118
将较大的整数传递给fibonacci函数时,它递归调用次数可能会超过MAXACTION或MAXNESTING的限制,SystemTap会在运行时捕捉到,并报告错误。
1.5 stap命令
Stap程序是SystemTap工具的前端,它接受使用脚本语言编写的探测指令(probing instructions),翻译成C代码,并将C代码编译成内核模块,接着将模块加载到内核,最后内核执行脚本里请求的系统跟踪和探测函数。你可从标准输入或命令行参数向stap提供脚本文件。程序运行直至用户中断,或者遇到大量的软件错误,或者脚本自动调用exit()函数。
Stap命令完成下述的工作:
关于stap命令的所有选项列表,请参阅stap(1)的用户手册。
1.6 安全情况
SystemTap是一个管理工具,它暴露了内核的内部数据结构和用户潜在的私有信息。它要求root权限来运行内核对象,使用sudo命令来运行staprun程序。
Staprun是SystemTap软件包的一部分,专门用于加载和卸载内核模块,以及内核到用户空间的数据转换。由于staprun并没有对给定的内核对象进行额外的安全检查,因此对可疑用户(untrustedusers),它不需要通过sudo来提升权限。
转换器保证某些安全约束。它确保处理例程不可以运行得太久,不可以分配内存,不可以执行不安全操作,即使是无意地干预内核也不行。使用脚本全局变量加锁来避免探测函数的并发运行。使用guru模式结构如embedded C(参考3.5节)会违背这些约速,导致内核crash和数据corruption。
各种资源的使用限制由所生成的C代码中的宏来设置。这些值可在编译时由-D选项来重写。下面描述了部分挑选出来的宏:
MAXNESTING 递归函数的最大调用层数,默认值是10。
MAXSTRINGLEN 字符串的最大长度,默认值是128。
MAXTRYLOCK 在声称可以出现死锁和跳出探测点前,等待全局变量锁的最大迭代次数,默认值是1000。
MAXACTION 单个探测点内可以执行语句数的最大值,默认值是1000。
MAXMAPENTRIES 数组在声明时没有显示指定大小时,数组的最大行数(译者注:即组数的最大下标个数),默认值为2048。
MAXERRORS 在触发退出前,可以容忍软件错误个数的最大值,默认值是0。
MAXSKIPPED 在触发退出前,可忽略的重入探测点的最大值,默认值是100。
MINSTACKSPACE 运行探测处理函数所需要的内核栈的最小字节数。此数值应比探测处理函数所需内核栈的大小加上安全边界大小足够大。默认值是1024。
Stap或statrun如果在探测点已经运行之后出现问题,可以安全杀死(kill)用户空间进程,并且可以使用rmmod命令删除内核探测模块。任何未处理的跟踪消息将丢失。