<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Systemtap on codedump notes</title>
    <link>https://www.codedump.info/zh/tags/systemtap/</link>
    <description>Recent content in Systemtap on codedump notes</description>
    <generator>Hugo</generator>
    <language>zh</language>
    <lastBuildDate>Tue, 18 Feb 2020 17:37:01 +0800</lastBuildDate>
    <atom:link href="https://www.codedump.info/zh/tags/systemtap/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Systemtap中内核trace事件的实现</title>
      <link>https://www.codedump.info/zh/post/20200218-linux-traceevent/</link>
      <pubDate>Tue, 18 Feb 2020 17:37:01 +0800</pubDate>
      <guid>https://www.codedump.info/zh/post/20200218-linux-traceevent/</guid>
      <description>&lt;h1 class=&#34;heading&#34; id=&#34;概述&#34;&gt;&#xA;  概述&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#%e6%a6%82%e8%bf%b0&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&lt;p&gt;内核中定义了一系列的trace point，这些trace point在特定的内核函数中被触发调用时被记录，而对应到systemtap中就是&lt;code&gt;kernel.trace&lt;/code&gt;类型的probe事件，可以使用命令来查看系统所有的trace point：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;$ sudo stap -L &amp;#39;kernel.trace(&amp;#34;*&amp;#34;)&amp;#39; | more&#xA;kernel.trace(&amp;#34;9p:9p_client_req&amp;#34;) $clnt:struct p9_client* $type:int8_t $tag:int&#xA;kernel.trace(&amp;#34;9p:9p_client_res&amp;#34;) $clnt:struct p9_client* $type:int8_t $tag:int $err:int&#xA;kernel.trace(&amp;#34;9p:9p_protocol_dump&amp;#34;) $clnt:struct p9_client* $pdu:struct p9_fcall*&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;换言之，通过systemtap能够对这些已经静态注册的内核调用记录点进行监控、跟踪。&lt;/p&gt;&#xA;&lt;p&gt;以下来解释trace point在内核的实现以及与systemtap相关的内容。&lt;/p&gt;&#xA;&lt;h1 class=&#34;heading&#34; id=&#34;数据结构&#34;&gt;&#xA;  数据结构&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#%e6%95%b0%e6%8d%ae%e7%bb%93%e6%9e%84&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&lt;p&gt;内核通过&lt;code&gt;DECLARE_TRACE&lt;/code&gt;来声明一个trace point：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;DECLARE_TRACE(subsys_eventname,&#xA;&#x9;TP_PROTO(int firstarg, struct task_struct *p),&#xA;&#x9;TP_ARGS(firstarg, p));&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;在这里：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;subsys_eventname是定义trace事件的唯一字符串，又能拆解成两部分：subsys就是子系统的名称，而eventname是事件名称。比如下面将作为实例的&lt;code&gt;softirq_entry&lt;/code&gt;，就定义了一个在&lt;code&gt;softirq&lt;/code&gt;子系统中的&lt;code&gt;entry&lt;/code&gt;事件。&lt;/li&gt;&#xA;&lt;li&gt;TP_PROTO(int firstarg, struct task_struct *p)：定义了传入trace函数的参数原型。&lt;/li&gt;&#xA;&lt;li&gt;TP_ARGS(firstarg, p)：定义了参数名称，其类型与TP_PROTO中的类型一一对应。&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;这个宏的定义如下：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C&#34; data-lang=&#34;C&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// include/linux/tracepoint.h&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#define DECLARE_TRACE(name, proto, args)&#x9;&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;&#x9;__DECLARE_TRACE(name, PARAMS(proto), PARAMS(args),&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;&#x9;&#x9;&#x9;cpu_online(raw_smp_processor_id()),&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;&#x9;&#x9;&#x9;PARAMS(void *__data, proto),&#x9;&#x9;&#x9;\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;&#x9;&#x9;&#x9;PARAMS(__data, args))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其中的宏&lt;code&gt;__DECLARE_TRACE&lt;/code&gt;定义如下：&lt;/p&gt;</description>
    </item>
    <item>
      <title>通过实例快速入门Systemtap</title>
      <link>https://www.codedump.info/zh/post/20200128-systemtap-by-example/</link>
      <pubDate>Tue, 28 Jan 2020 11:56:56 +0800</pubDate>
      <guid>https://www.codedump.info/zh/post/20200128-systemtap-by-example/</guid>
      <description>&lt;p&gt;我这段时间好好学习了一下Systemtap相关的使用，这篇文章算是学习过程中总结的一些笔记，我另外在github上创建了一个&lt;a href=&#34;https://github.com/lichuang/awesome-systemtap-cn&#34;&gt;awesome-systemtap-cn&lt;/a&gt;项目，收集systemtap相关的优秀学习资源，欢迎提供其他更好的参考资料。&lt;/p&gt;&#xA;&lt;h1 class=&#34;heading&#34; id=&#34;概述&#34;&gt;&#xA;  概述&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#%e6%a6%82%e8%bf%b0&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&lt;p&gt;systemtap是一款“动态跟踪（dynamic tracing）”工具，为什么需要这类工具？打一个比方，这类工具就好比医生的听诊器，病人就好比是在运行的系统，很多时候查看一些问题需要在系统在运行的时候来观察，这时候就需要这类动态跟踪工具。与之对应的是，类似gdb这样的调试工具，其工作原理是让进程在某些断点暂停下来，查看进程的行为，这种技术称为“静态调试”。&lt;/p&gt;&#xA;&lt;p&gt;关于动态跟踪技术，推荐阅读&lt;a href=&#34;https://openresty.org/posts/dynamic-tracing/&#34;&gt;《动态追踪技术漫谈》&lt;/a&gt;。&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&gt;&#xA;&#xA;    &lt;div&gt;&#xA;        &lt;img loading=&#34;lazy&#34; alt=&#34;Smileytap.svg&#34; src=&#34;https://www.codedump.info/media/imgs/20200128-systemtap-by-example/Smileytap.svg_.png&#34; &gt;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;caption-container&#34;&gt;&#xA;        &lt;figcaption&gt; systemtap &lt;/figcaption&gt;&#xA;    &lt;/div&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&lt;/p&gt;&#xA;&lt;p&gt;本文旨在通过实例，快速解释systemtap脚本语言的最常见用法和语法。&lt;/p&gt;&#xA;&lt;h1 class=&#34;heading&#34; id=&#34;工作原理&#34;&gt;&#xA;  工作原理&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#%e5%b7%a5%e4%bd%9c%e5%8e%9f%e7%90%86&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&lt;p&gt;如下图，systemtap使用.stp脚本语言，由命令行&lt;code&gt;stap&lt;/code&gt;编译生成对应的内核模块，动态放入内核中执行：&lt;/p&gt;&#xA;&lt;p&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;figure class=&#34;&#34;&gt;&#xA;&#xA;    &lt;div&gt;&#xA;        &lt;img loading=&#34;lazy&#34; alt=&#34;systemtap&#34; src=&#34;https://www.codedump.info/media/imgs/20200128-systemtap-by-example/systemtap.gif&#34; &gt;&#xA;    &lt;/div&gt;&#xA;&#xA;    &#xA;    &lt;div class=&#34;caption-container&#34;&gt;&#xA;        &lt;figcaption&gt; systemtap &lt;/figcaption&gt;&#xA;    &lt;/div&gt;&#xA;    &#xA;&lt;/figure&gt;&#xA;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;stap 流程从将脚本转换成解析树开始 (pass 1)。&lt;/li&gt;&#xA;&lt;li&gt;然后使用细化（elaboration）步骤 (pass 2) 中关于当前运行的内核的符号信息解析符号。&lt;/li&gt;&#xA;&lt;li&gt;接下来，转换流程将解析树转换成 C 源代码 (pass 3) 并使用解析后的信息和 tapset 脚本（SystemTap 定义的库，包含有用的功能）。&lt;/li&gt;&#xA;&lt;li&gt;stap 的最后步骤是构造使用本地内核模块构建进程的内核模块 (pass 4)。&lt;/li&gt;&#xA;&lt;li&gt;有了可用的内核模块之后，stap 完成了自己的任务，并将控制权交给其他两个实用程序 SystemTap：staprun 和 stapio。这两个实用程序协调工作，负责将模块安装到内核中并将输出发送到 stdout (pass 5)。如果在 shell 中按组合键 Ctrl-C 或脚本退出，将执行清除进程，这将导致卸载模块并退出所有相关的实用程序。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h1 class=&#34;heading&#34; id=&#34;stap命令行参数&#34;&gt;&#xA;  stap命令行参数&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#stap%e5%91%bd%e4%bb%a4%e8%a1%8c%e5%8f%82%e6%95%b0&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&lt;h2 class=&#34;heading&#34; id=&#34;-x-pid&#34;&gt;&#xA;  -x PID&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#-x-pid&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;-x用于传递PID参数给systemtap脚本，这样在脚本内部可以通过target()函数拿到这个传递进来的参数：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;// $ sudo stap x-param.stp -x 10&#xA;// 输出：pid:10&#xA;probe begin&#xA;{&#xA;  printf(&amp;#34;pid:%d\n&amp;#34;, target())&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;h2 class=&#34;heading&#34; id=&#34;-t-seconds&#34;&gt;&#xA;  -T seconds&#xA;  &lt;a class=&#34;anchor&#34; href=&#34;#-t-seconds&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;-T 参数后面可以带上秒数，这样脚本在这个时间之后自动退出，这样可以设置脚本执行的时间。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
