一、systemtap介绍

  SystemTap是一个强大的调试工具,是监控和跟踪运行中的Linux 内核的操作的动态方法,确切的说应该是一门调试语言,因为它有自己的语法,也有解析、编译、运行等过程(准确的说有五个阶段)。

  但它主要解决的问题是收集Linux内核或者用户进程的信息,主要目的是调试。

  gdb、kgdb同是linux最强大的调试器,gdb和SystemTap不是竞争关系,而是互补关系,gdb能做的事情SystemTap做不到,比如断点/watch变量等等这些SystemTap都做不到,

  而SystemTap能做的事情gdb做不到或者非常麻烦才做到,比如很方便查看内核调试栈/嵌入C语言等等gdb就很难。

  SystemTap 是一款诊断Linux系统性能的工具,可以跟踪内核以及用户态程序中的任意函数、syscall、语句甚至指令,可以用来动态地收集调试和性能信息的工具,不需要我们重新编译、重启内核。缺点:用户需要自己编辑脚本测试文件。

  假如现在有这么一个需求:需要获取正在运行的 Linux 系统的信息,如我想知道系统什么时候发生系统调用,发生的是什么系统调用等这些信息,有什么解决方案呢?

  • 最原始的方法是,找到内核系统调用的代码,加上我们需要获得信息的代码、重新编译内核、安装、选择我们新编译的内核重启。这种做法对于内核开发人员简直是梦魇,因为一遍做下来至少得需要1个多小时,不仅破坏了原有内核代码,而且如果换了一个需求又得重新做一遍上面的工作。所以,这种调试内核的方法效率是极其底下的。
  • 之后内核引入了一种Kprobe机制,可以用来动态地收集调试和性能信息的工具,是一种非破坏性的工具,用户可以用它跟踪运行中内核任何函数或执行的指令等。相比之前的做法已经有了质的提高了,但Kprobe并没有提供一种易用的框架,用户需要自己去写模块,然后安装,对用户的要求还是蛮高的。
  • systemtap 是利用Kprobe 提供的API来实现动态地监控和跟踪运行中的Linux内核的工具,相比Kprobe,systemtap更加简单,提供给用户简单的命令行接口,以及编写内核指令的脚本语言。对于开发人员,systemtap是一款难得的工具。

二、systemtap安装

1.安装步骤:

  查看环境:uname -r

  yum install kernel-devel

  yum install systemtap

  install kernel/glib debug:

  glibc-debuginfo-2.17-106.el7_2.8.x86_64.rpm 
  glibc-debuginfo-common-2.17-106.el7_2.8.x86_64.rpm 
  kernel-debuginfo-3.10.0-327.28.3.el7.x86_64.rpm 
  kernel-debuginfo-common-x86_64-3.10.0-327.28.3.el7.x86_64.rpm 
  ref: http://debuginfo.centos.org/7

下载kernel-debuginfo 以及kernel-debuginfo-common,要下载对应内核版本的(错误版本会提示semantic error: no match等报错);

测试是否安装ok: 
  1.1 测试stap

[root@root conf]# stap -V
Systemtap translator/driver (version 3.2/0.168/0.166, commit release-3.1-210-g3decfea497ac + changes)
Copyright (C) 2005-2017 Red Hat, Inc. and others
This is free software; see the source for copying conditions.
tested kernel versions: 2.6.18 ... 4.11
enabled features: JAVA PYTHON2 LIBSQLITE3 LIBXML2 NLS

  1.2 测试kernel-debuginfo

[root@root conf]# stap -L 'kernel.function("printk")'
kernel.function("printk@kernel/printk.c:1693") $fmt:char const* $args:va_list

  1.3 测试glibc-debuginfo

[root@kuber-worker- conf]# stap -L 'process("/lib64/libc.so.6").function("malloc")'
process("/usr/lib64/libc-2.17.so").function("malloc")

   1.4 其他测试示例 打印hello systemtap

   以root用户或者具有sudo权限的用户运行以下命令:

[root@root conf]# stap -ve 'probe begin { log("hello systemtap!") exit() }'
Pass : parsed user script and library scripts using 193340virt/58416res/2252shr/56848data kb, in 380usr/40sys/420real ms.
Pass : analyzed script: probe, functions, embeds, globals using 194660virt/59996res/2488shr/58168data kb, in 20usr/0sys/14real ms.
Pass : using cached /root/.systemtap/cache/2f/stap_2fdbfdf450adaf1c0592d368ccee2be4_1142.c
Pass : using cached /root/.systemtap/cache/2f/stap_2fdbfdf450adaf1c0592d368ccee2be4_1142.ko
Pass : starting run.
hello systemtap!
Pass : run completed in 10usr/60sys/413real ms.

  1.5 其他测试示例 输出4s内所有open系统调用的信息

  创建systemtap脚本文件test2.stp:

#!/usr/bin/stap

probe begin
{
log("begin to probe")
} probe syscall.open
{
printf ("%s(%d) open (%s)\n", execname(), pid(), argstr)
} probe timer.ms() # after seconds
{
exit ()
} probe end
{
log("end to probe")
}

将该脚本添加可执行的权限 chmod +x test2.stp ,使用./test2.stp 运行该脚本,即可输出4s内所有open系统调用的信息,打印格式为:进程名(进程号)打开什么文件。

大家可以自行去测试,如果两个示例都能正确运行,基本上算是安装成功了!

systemtap 工作原理

systemtap 的核心思想是定义一个事件(event),以及给出处理该事件的句柄(Handler)。

当一个特定的事件发生时,内核运行该处理句柄,就像快速调用一个子函数一样,处理完之后恢复到内核原始状态。

这里有两个概念:

  • 事件(Event):systemtap 定义了很多种事件,例如进入或退出某个内核函数、定时器时间到、整个systemtap会话启动或退出等等。
  • 句柄(Handler):就是一些脚本语句,描述了当事件发生时要完成的工作,通常是从事件的上下文提取数据,将它们存入内部变量中,或者打印出来。

Systemtap 工作原理是通过将脚本语句翻译成C语句,编译成内核模块。

模块加载之后,将所有探测的事件以钩子的方式挂到内核上,当任何处理器上的某个事件发生时,相应钩子上句柄就会被执行。

最后,当systemtap会话结束之后,钩子从内核上取下,移除模块。整个过程用一个命令 stap 就可以完成。

上面只是简单的原理,更多背后的机理参考网上资料和相应的论文。

systemtap官网: https://sourceware.org/systemtap/documentation.html

三、实战应用及常用工具瓶颈

  1.故障处理中遇到的困境:

  1.1 iostat等命令看到的是系统级的统计,比如下例中我们看到/dev/vdb很忙,如果要追查是哪个进程导致的I/O繁忙,应该怎么办?

  

  进程的内核数据结构中包含了I/O数量的统计:

  struct task_struct {

        struct task_io_accounting ioac;
    };
 
  可以直接在 /proc/<pid>/io 中看到:

  # cat /proc/3088/io
 
   rchar: 125119 //在read(),pread(),readv(),sendfile等系统调用中读取的字节数
   wchar: 632    //在write(),pwrite(),writev(),sendfile等系统调用中写入的字节数
   syscr: 111    //调用read(),pread(),readv(),sendfile等系统调用的次数
   syscw: 79     //调用write(),pwrite(),writev(),sendfile等系统调用的次数
   read_bytes: 425984 //进程读取的物理I/O字节数,包括mmap pagein,在submit_bio()中统计的
   write_bytes: 0     //进程写出的物理I/O字节数,包括mmap pageout,在submit_bio()中统计的
   cancelled_write_bytes: 0 //如果进程截短了cache中的文件,事实上就减少了原本要发生的写I/O
 
  我们关心的是实际发生的物理I/O,从上面的注释可知,应该关注 read_bytes 和 write_bytes。
    请注意这都是历史累计值,从进程开始执行之初就一直累加。
  如果要 观察动态变化情况,可以使用 pidstat 命令,它就是利用了/proc/<pid>/io 中的原始数据计算单位时间内的增量:
 
  

  另外还有一个常用的命令 iotop 也可以观察进程的动态I/O:

          

pidstat 和 iotop 也有不足之处,它们无法具体到某个硬盘设备,如果系统中有很多硬盘设备,都在忙,而我们只想看某一个特定的硬盘的I/O来自哪些进程,这两个命令就帮不上忙了。

    怎么办呢?

  2.SystemTap查找方法:

  可以用上万能SystemTap工具。比如:我们希望找出访问/dev/vdb的进程,可以用下列脚本,它的原理是对submit_bio下探针:

     [root@template ~]# cat io_vdb.stap
   #! /usr/bin/env stap    global device_of_interest probe begin {
    device_of_interest = $
    printf ("device of interest: %x\n", device_of_interest)
    }    probe kernel.function("submit_bio")
   {
    dev = $bio->bi_bdev->bd_dev
    if (dev == device_of_interest)
      printf ("[%s](%d) dev:0x%x rw:%d size:%d\n",
       execname(), pid(), dev, $rw, $bio->bi_size)
   }

  这个脚本需要在命令行参数中指定需要监控的硬盘设备号,得到这个设备号(fc,10)的方法如下:

十六进制: (fc,10)---->(主设备号Major number(12-bit),次设备号Minor number(20-bit))  需要转换为10进制作为io_vdb.stap的入参数($1)

十进制:(252,10)

  stat /dev/vdb:

  cat /proc/devices:

  3.SystemTap 查证结果:

  3.1 查看某个分区或目录io访问情况:

  脚本执行命令:./io_vdb 264241171

  (264241171为 fc00013的十进制表示,因为 fc00010为/dev/vdb,我们的测试目录为/dev/vdb3,所以对应的次设备号变为13(fc,13))

执行grep命令进行验证io实际执行情况:

执行前:

  执行后:

  通过结果,我们看到是进程号为8446的grep命令在对/dev/vdb3进行读操作(rw:0)。

               

   Enjoyjing youeself!

参考文章:

  http://linuxperf.com/?cat=4

  http://www.xbwolf.com/507

  http://blog.csdn.net/wangzuxi/article/details/42849053

Linux systemtap定位系统IO资源使用情况(ok)的更多相关文章

  1. linux查看资源占用情况

    在Linux中查看占用空间大文件 查看当前目录总共占的容量.而不单独列出各子项占用的容量$ du -sh查看当前目录下一级子文件和子目录占用的磁盘容量.$ du -lh --max-depth=1结果 ...

  2. 操作系统复习——如何查看一个进程的详细信息,如何追踪一个进程的执行过程 ,如何在 Linux 系统下查看 CPU、内存、磁盘、IO、网卡情况?epoll和select区别?

    1. 如何查看一个进程的详细信息,如何追踪一个进程的执行过程 通过pstree命令(根据pid)进行查询进程内部当前运行了多少线程:# pstree -p 19135(进程号) 使用top命令查看(可 ...

  3. 深入理解JAVA I/O系列六:Linux中的IO模型

    IO模型 linux系统IO分为内核准备数据和将数据从内核拷贝到用户空间两个阶段. 这张图大致描述了数据从外部磁盘向运行中程序的内存中移动的过程. 用户空间.内核空间 现在操作系统都是采用虚拟存储器, ...

  4. Linux优化之IO子系统监控与调优

    Linux优化之IO子系统 作为服务器主机来讲,最大的两个IO类型 : 1.磁盘IO 2.网络IO 这是我们调整最多的两个部分所在 磁盘IO是如何实现的 在内存调优中,一直在讲到为了加速性能,linu ...

  5. Linux SCSI回调IO的分析

    本文转载自:http://blog.csdn.net/xushiyan/article/details/6941640,如需参考,请访问原始链接地址. 没找到如何转载的入口,只好全文copy了. -- ...

  6. Linux下的IO监控与分析

    Linux下的IO监控与分析 近期要在公司内部做个Linux IO方面的培训, 整理下手头的资料给大家分享下 各种IO监视工具在Linux IO 体系结构中的位置 源自 Linux Performan ...

  7. 深入理解JAVA I/O系列六:Linux中的IO模型(转载的文章非常值得学习)

    From:http://www.cnblogs.com/dongguacai/p/5770287.html IO模型 linux系统IO分为内核准备数据和将数据从内核拷贝到用户空间两个阶段. 这张图大 ...

  8. 【转载】Linux下的IO监控与分析

    近期要在公司内部做个Linux IO方面的培训, 整理下手头的资料给大家分享下 各种IO监视工具在Linux IO 体系结构中的位置 源自 Linux Performance and Tuning G ...

  9. linux服务器查看IO

    为了方便各位和自己今后遇到此类问题能尽快解决,我这里将查看linux服务器硬盘IO访问负荷的方法同大家一起分享: 首先 .用top命令查看 top - 16:15:05 up 6 days,  6:2 ...

随机推荐

  1. asp.net core 系列 1 概述

    一.   概述 ASP.NET Core 是一个跨平台的高性能开源框架,可以用来:建置 Web 应用程序和服务.IoT应用和移动后端.在 Windows macOS 和 Linux 上使用喜爱的开发工 ...

  2. 文本主题模型之潜在语义索引(LSI)

    在文本挖掘中,主题模型是比较特殊的一块,它的思想不同于我们常用的机器学习算法,因此这里我们需要专门来总结文本主题模型的算法.本文关注于潜在语义索引算法(LSI)的原理. 1. 文本主题模型的问题特点 ...

  3. 初学Java Web(5)——cookie-session学习

    HTTP 协议 Web 浏览器与 Web 服务器之间的一问一答的交互过程必须遵守一定的规则,这样的规则就是 HTTP 协议. HTTP 是 hypertext transfer protocol(超文 ...

  4. 五一之起一台服务器玩玩-centosl系统搭建lamp

    昨天看到有的扫描软件会扫描公网主机开放的端口,我现在就用了ssh远程登录21和22端口那不是很容易被猜想到.so,我决定要改这个端口,同时这个改端口给我打开了防火墙和ip协议和网络安全的大门. 我之前 ...

  5. ssh-login 一键密码加密登录工具

    ssh-login 1. Feature 管理多个帐号,每个帐号一个易记的 tip name,支持 tab 进行 tip name 补全,一键 ssh 登录 密码 AES 加密,密文存储密码,且只需要 ...

  6. 程序员如何描述清楚线上bug

    案例 一个管理后台的bug,把操作记录中的操作员姓名,写成了该操作员的id.原因是修改了一个返回操作人姓名的函数,返回了操作人的id.但是还有其他地方也用这个函数,导致其他地方把姓名字段填写成了操作员 ...

  7. Java开发笔记(二十二)神奇的冒号

    Java中的标点符号主要有两类用途,一类是运算符,包括加号+.减号-.乘号*.除号/.取余号%.等号=.大于号>.小于号<.与号&.或号|.非号!.异或号^等等,另一类则是分隔符, ...

  8. 2018.12/6 js键盘事件 DOM:0级2级

    DOM0级事件元素绑定多个click最后只执行最后一个click. DOM2级事件元素绑定多个click,都要执行 注意当绑定的多个事件名,函数名,事件发生阶段三者完全一样时,才执行最后一个 div. ...

  9. JavaScript(二)

    本文转载自https://blog.csdn.net/xiaogeldx/article/details/85412716 JavaScript操作符 算术运算符 算术运算符有:+,-,*,/,%,+ ...

  10. 小记 xian80 坐标转换 wgs84

    转坐标这个问题是个老生常谈的话题了. 昨天遇到同事求助将 xian80的平面坐标转换到2000下. 想了一下,因为暂时还没有现成的2000的dwg数据可用,只能暂时以wgs84的为准了,然而有个问题, ...