《System语言详解》——1.SystemTap概述

本文介绍SystemTap的基础知识,包括其语法、控制结构和脚本示例。SystemTap是一种用于Linux内核性能分析和调试的强大工具。

 

英文原文: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语言是一种强类型的,免声明的,面向过程的和起源于dtraceawk的语言。它将内核中的源代码点和事件关联到处理函数(handler),这些处理函数是异步执行的子例程。探测点(probe)在概念上与GDB调试器上的“断点命令列表”相似类。

SystemTap有两个最外层的结构:探测点和函数。它的语句和表达式使用类C语言的操作符语法和优先级。

1.4 SystemTap脚本范例

下面是一个展示SystemTap基本操作的脚本例子。更多例子,请参阅源代码中的examples/small_demos/目录,SystemTap维基http://sourceware.org/systemtap/wiki/HomePageSystemTap War Stories http://sourceware.org/systemtap/wiki/WarStories

1.4.1 SystemTap基础语法和控制结构

下面代码示例演示了SystemTap语法和控制结构。

global odds, evens

 

probe begin {

    # none是局部整型变量

    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 049之间的质数

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函数时,它递归调用次数可能会超过MAXACTIONMAXNESTING的限制,SystemTap会在运行时捕捉到,并报告错误。

1.5 stap命令

Stap程序是SystemTap工具的前端,它接受使用脚本语言编写的探测指令(probing instructions),翻译成C代码,并将C代码编译成内核模块,接着将模块加载到内核,最后内核执行脚本里请求的系统跟踪和探测函数。你可从标准输入或命令行参数向stap提供脚本文件。程序运行直至用户中断,或者遇到大量的软件错误,或者脚本自动调用exit()函数。

Stap命令完成下述的工作:

  • 翻译脚本
  • 生成C代码并编译成内核模块
  • 加载模块到内核,输出到stapstdout
  • CTRL-C卸载内核模块和终止stap

关于stap命令的所有选项列表,请参阅stap(1)的用户手册。

1.6 安全情况

SystemTap是一个管理工具,它暴露了内核的内部数据结构和用户潜在的私有信息。它要求root权限来运行内核对象,使用sudo命令来运行staprun程序。

StaprunSystemTap软件包的一部分,专门用于加载和卸载内核模块,以及内核到用户空间的数据转换。由于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

Stapstatrun如果在探测点已经运行之后出现问题,可以安全杀死(kill)用户空间进程,并且可以使用rmmod命令删除内核探测模块。任何未处理的跟踪消息将丢失。

<think>我们正在讨论SystemTap,这是一个用于Linux系统的动态追踪工具,允许用户监控和诊断内核及用户空间程序的运行情况。SystemTap通过编写脚本(以.stp为后缀)来定义事件和对应的处理程序,实现实时数据收集和分析。 关键概念: 1. **探针(Probes)**:定义事件点(如函数入口、出口、定时器等),当事件发生时执行关联的处理程序。 2. **处理程序(Handlers)**:当探针触发时执行的一组脚本语句。 3. **Tapset**:预定义的探针和函数库,简化脚本编写。 基本语法: ``` probe probe_point [, probe_point] { handler_statement } ``` 示例脚本:监控进程的execve系统调用 ``` probe syscall.execve { printf("%s(%d) executed %s\n", execname(), pid(), argstr) } ``` 安装与运行: 在大多数Linux发行版中,可以通过包管理器安装SystemTap: ``` sudo apt-get install systemtap # Debian/Ubuntu sudo yum install systemtap # CentOS/RHEL ``` 运行脚本: ``` stap script.stp ``` 高级特性: - **条件语句**:在探针中设置条件,例如`if(pid()==target())` - **关联数组**:用于聚合数据,例如统计函数调用次数 - **嵌入C代码**:通过`%{ ... %}`嵌入C代码,用于复杂操作 调试与优化: - 使用`-v`选项增加详细输出 - 使用`-pN`仅进行解析或预处理(不运行) - 使用`-g`开启guru模式,允许嵌入C代码 安全机制: SystemTap脚本默认需要root权限,但可以通过签名机制允许普通用户运行受信任的脚本。 注意事项: - 生产环境使用前应在测试环境充分验证 - 避免在探针中执行耗时操作,以免影响系统性能 参考文档: - SystemTap官方文档:https://sourceware.org/systemtap/documentation.html - 《SystemTap Beginners Guide》 接下来,我将生成一些相关问题,以帮助用户深入学习SystemTap。</think>### SystemTap 详解与使用指南 SystemTapLinux 系统的动态追踪工具,允许用户实时监控和分析内核及用户空间程序的运行状态。它通过注入探针(probe)到内核和应用程序中,实现低开销的运行时诊断[^1]。 #### 核心组件 1. **探针(Probes)** 事件触发点,语法:`probe event { statements }` 常见事件类型: - 内核事件:`kernel.function("sys_open")` - 用户空间事件:`process("nginx").function("ngx_http_process_request")` - 定时器:`timer.s(5)`(每5秒触发) 2. **Tapset 库** 预定义的探针和函数库,路径:`/usr/share/systemtap/tapset/` 3. **Stap 编译器** 工作流程: $$脚本(.stp) \xrightarrow{stap} C代码 \xrightarrow{gcc} 内核模块(.ko) \xrightarrow{insmod} 运行$$ #### 基础语法示例 ```c probe begin { printf("SystemTap started\n") } probe syscall.open { printf("%s opened %s\n", execname(), filename) } probe timer.s(10) { exit() } ``` 运行:`stap demo.stp` #### 高级功能 1. **变量与统计** ```c global count probe syscall.write { count++ } probe end { printf("Write syscalls: %d\n", count) } ``` 2. **条件过滤** ```c probe syscall.* if (pid() == target()) { printf("%s called by %d\n", name, pid()) } ``` 3. **调用栈追踪** ```c probe kernel.function("vfs_read") { print_backtrace() } ``` 4. **性能分析** ```c probe timer.profile { printf("%s\n", ppfunc()) } ``` #### 安全机制 - 需要`root`权限或`stapdev`组权限 - 数字签名验证(`stap --sign`) - 资源限制(`MAXNESTING`,`MAXACTION`等) #### 调试技巧 1. 详细模式:`stap -v script.stp` 2. 预检模式:`stap -p3 script.stp`(仅生成C代码) 3. 日志输出:`stap -L 'kernel.function("*")'` #### 典型应用场景 1. **性能瓶颈分析** ```c probe kernel.function("do_sys_open") { t = gettimeofday_us() } probe kernel.function("do_sys_open").return { printf("open took %d us\n", gettimeofday_us() - t) } ``` 2. **内存泄漏检测** ```c probe kmem.kmalloc { allocations[pid(), $caller] <<< $size } probe kmem.kfree { deallocations[pid(), $caller] <<< $size } ``` 3. **网络包分析** ```c probe netdev.receive { printf("%s: %d bytes\n", name, length) } ``` [^1]: SystemTap 官方文档 https://sourceware.org/systemtap/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值