ust (user space tracer)

来源:互联网 发布:大学生网络直播 编辑:程序博客网 时间:2024/05/01 08:29

last modified:

08-09-2011 

---------------

ref:http://lttng.org/files/ust/manual/ust.html

1.1 UST(Userspace Tracer)
UST是一个带有一系列跟踪用户空间代码的工具的库。
代码可以插入maker或者tracepoint。高性能的无锁tracer记录这些事件到
trace buffer。一个守护进程从这些buffer中获取数据并写到磁盘上。
通过使用无锁缓冲算法,RCU和per-cpu缓冲区,达到了很高的性能。
另外,也特殊注意减少对cache的影响。
1.3 支持的平台
当前UST可以运行在装有Llinux的 x86-32, x86-64和PowerPC 32位体系结构上。

2. 安装
需要安装如下的包:
- ust
 包括跟踪库,ustd 守护进程,跟踪控制工具和其他的帮助工具。
仓库:git://git.lttng.org/ust.git
              http://git.lttng.org//ust.git
- liburcu
 用户空间的read-copy-update 库。
 在debian上可用的包是 liburcu-dev
 主页: http://lttng.org/urcu
- LTTV
 LTTng traces的图形化观察器。
主页:http://lttng.org

liburcu需要首先安装。 UST才可以被编译和安装。LTTV是独立的。
下面,我们安装上面的包。
对于liburcu:
在debian上:#aptitude install liburcu-dev即可
下面看一下,从源码安装:
#wget -c http://lttng.org/files/urcu/userspace-rcu-0.6.4.tar.bz2  //下载包
#tar -jxf  userspace-rcu-0.6.4.tar.bz2
#cd userspace-rcu-0.6.4
//#./bootstrap (我们使用tar包安装,跳过这一步)
#./configure
#make
#make install
#ldconfig
OK.
下面开始装UST:
# git clone git://git.lttng.org/ust.git  //下载仓库
#aptitude install dh-autoreconf   //安装必要的工具
# cd ust
#./bootstrap
#./configure
#make
#make install
#ldconfig
OK
==================
3. Qs
首先,为一个程序装上一个marker。
//foo.c
#include <ust/marker.h>
     
     int main(int argc, char **argv)
     {
         int v;
         char *st;
     
         /* ... set values of v and st ... */
        v = 110;
        st = "hello, UST";
         /* a marker: */
         trace_mark(ust, myevent, "firstarg %d secondarg %s", v, st);
     
         /* a marker without arguments: */
         trace_mark(ust, myotherevent, MARK_NOARGS);
     
         return 0;
     }
 生成可执行程序:
#gcc -o foo -lust foo.c
使用usttrace运行程序。
#mkdir /tmp/mytrace
#usttrace -o /tmp/mytrace ./foo
Waiting for ust-consumerd to shutdown...
Trace was output in:  /tmp/mytrace
#tree  /tmp/mytrace
/tmp/mytrace
├── 21402_147523
│   ├── metadata_0
│   └── ust_0
├── app.log
└── ust-consumerd.log

最后,使用LTTV打开trace。
#lttv-gui -t /tmp/mytrace/21060_900246
或者以字符形式显示在终端:
# lttv -m textDump -t /tmp/mytrace/21402_147523
...
ust.myevent: 102427.849378367 (/tmp/mytrace/21402_147523/ust_0), 0, 0, , , 0, 0x0, MODE_UNKNOWN { firstarg = 110, secondarg = "hello, UST" }
...
待续。。。

09_08_2011
==========
4 检测一个应用程序
为了记录发生在应用程序的事件,这个程序必须被检测(instrumented)。检测点类似于系统调用。
当程序达到检测点,一个事件就会触发。对于能够被检测的代码类型没有什么限制。
多线程程序,信号处理程序等都可以被检测(instrumented)。

有两种API来检测程序:maker 和 tracepoint。marker可以快速添加,通常被用来做临时检测。
tracepoint提供了一种更简洁的适合永久检测(instrumentation)的方法。

4.1 markers
添加一个marker只需要在程序中添加一行。

#include <ust/marker.h>     
     int main(int argc, char **argv)
     {
         int v;
         char *st;
     
         /* ... set values of v and st ... */
     
         /* a marker: */
         trace_mark(main, myevent, "firstarg %d secondarg %s", v, st);
     
         /* another marker without arguments: */
         trace_mark(main, myotherevent, MARK_NOARGS);
     
         return 0;
     }
调用trace_mark()宏需要至少3个参数。第一个参数,在这里是“main”,是事件目录(event category)的名字。也是事件运行的通道(channel)。第二个参数,"myevent"是事件名字。第三个参数,
是格式化的字符串,声明了事件参数(event argument)的名字和类型。它的格式类似于printf()的格式字符串。
一个marker可以在同一个程序中重复出现。其他Marker可以有相同的名字但是不同的格式化字符串。但是,这会在分析时带来一些混淆。
4.2 tracepoint
tracepoint API使用了Marker,但是它提供更高层的抽象。鉴于Marker体统了有限的类型检查,
tracepoint API提供了更彻底的类型检查和从直接插入格式化字符串到当marker重用时使格式化字符串重复出现。
注意:虽然本例使用mychannel作为通道名字,但是对于当前支持的early tracing 的通道名是ust。
usttrace工具通常使用 early tracing mode. 当使用没有 early tracing的手动模式时,任何通道名字都可以使用。

一个添加了tracepoint的函数:
  ////ust_test.c
     #include "tp.h"     
     void myfunc()
     {
         int v = 123;
         char *st = "I am in myfunc.";
     
         /* ... set values of v and st ... */
     
         /* a tracepoint: */
         trace_mychannel_myevent(v, st);
     }
int main(void)
{
        myfunc();
        return 0;
}

另一个文件 tp.h包含了tracepoint的声明。
     #include <ust/tracepoint.h>
     
     DECLARE_TRACE(mychannel_myevent, TP_PROTO(int v, char *st),
               TP_ARGS(v, st));
另一个文件,tp.c,包含了tracepoint的定义。
     #include <ust/marker.h>
     #include "tp.h"     
     DEFINE_TRACE(mychannel_myevent);     
     void mychannel_myevent_probe(int v, char *st)
     {
         trace_mark(mychannel, myevent, "v %d st %s", v, st);
     }
     static void __attribute__((constructor)) init()
     {
         register_trace_mychannel_myevent(mychannel_myevent_probe);
       // printf("%s called \n", __func__);// 这个函数会被自动调用
     }
tp.h和tp.c可以包含其他tracepoint的定义和声明。构造器可以包含其他register_* 调用。


#gcc -o foo -lust tp.h tp.c ust_test.c
#usttrace -o /tmp/newtrace/ ./foo
Waiting for ust-consumerd to shutdown...
Trace was output in:  /tmp/newtrace/
#tree newtrace/
newtrace/
├── 24508_519505
│   ├── metadata_0
│   └── ust_0
├── app.log
└── ust-consumerd.log
# lttv -m textDump -t /tmp/newtrace/24508_519505
...
metadata.core_marker_id: 163473.951192646 (/tmp/newtrace/24508_519505/metadata_0), 0, 0, , , 0, 0x0, MODE_UNKNOWN { channel = "ust", name = "myevent", event_id = 1, int = 4, long = 4, pointer = 4, size_t = 4, alignment = 0 }
metadata.core_marker_format: 163473.951202982 (/tmp/newtrace/24508_519505/metadata_0), 0, 0, , , 0, 0x0, MODE_UNKNOWN { channel = "ust", name = "myevent", format = "v %d st %s" }
ust.myevent: 163473.951217604 (/tmp/newtrace/24508_519505/ust_0), 0, 0, , , 0, 0x0, MODE_UNKNOWN { v = 123, st = "I am in myfunc." }
...

5. 记录一个trace
记录一个trace最简单的方法就是使用 /usr/local/bin/usttrace 脚本(你可以打开看看它进行了那些操作)。
usttrace:
- 创建一个守护进程
- 使能所有的marker
- 运行命令行上指定的命令
- 执行完毕,打印出trace保存的位置
#tree newtrace/
newtrace/
├── 24508_519505 // PID_创建的时间戳
│   ├── metadata_0
│   └── ust_0
├── app.log // tracing logs
└── ust-consumerd.log
几个 usttrace可以同时没有冲突地执行。每一个usttrace的实例运行他们自己的守护进程
来收集它创建的进程的事件。

5.2 手动跟踪//???? 这里有些问题没有搞清楚
- 确保通信socket文件夹存在
 #mkdir /tmp/ustsocks
- 确保trace要写入文件夹存在
 #mkdir /tmp/trace
- 开始运行守护进程
#ustd  (./usr/local/bin/ust-consumerd)?????
- 假设我们要trace的程序已经开始运行并且它的pid是24974
- 列出所有可用的marker
#ustctl --list-markers 24974
- 0 表示非活动的marker,1表示活动的marker
{PID: 24974, channel/marker: metadata/core_marker_format, state: 1, fmt: "channel %s name %s format %s" (nil)}
{PID: 24974, channel/marker: metadata/core_marker_id, state: 1, fmt: "channel %s name %s event_id %hu int #1u%zu long #1u%zu pointer #1u%zu size_t #1u%zu alignment #1u%u" (nil)}
{PID: 24974, channel/marker: metadata/core_marker_format, state: 1, fmt: "channel %s name %s format %s" (nil)}
{PID: 24974, channel/marker: metadata/core_marker_id, state: 1, fmt: "channel %s name %s event_id %hu int #1u%zu long #1u%zu pointer #1u%zu size_t #1u%zu alignment #1u%u" (nil)}
{PID: 24974, channel/marker: metadata/core_marker_format, state: 1, fmt: "channel %s name %s format %s" (nil)}
{PID: 24974, channel/marker: ust/potential_exec, state: 0, fmt: " " (nil)}
{PID: 24974, channel/marker: ust/myevent, state: 0, fmt: "v %d st %s" (nil)}

- 使能 一个 marker
#ustctl --enable-marker ust/myevent 24974 // 可以再次运行 --list-markers 来检查是否已经使能
- 创建一个trace
#ustctl --create-trace 24974
-- 做些其他事情
-停止 trace
#ustctl --stop-trace 24974 //这里有些问题????
  //ustctl[25317/25317]: Error: Failed to stop trace auto for PID 24974
  //  (in stop_trace() at trace_cmds.c:73)

-销毁trace
#ustctl --destroy-trace 24974

========= 使用 early tracing
early tracing 包括尽早的开始跟踪。这样在程序开始运行到运行跟踪命令之间没有事件丢失。
它可以确保在程序进入main()之前,跟踪就开始了。
使用 early tracing 只要把 环境变量 UST_TRACE 设置为1就可以了。
把UST_AUTOPROBE设置为1就自动使能所有marker。

其他信息,参看 http://lttng.org/files/ust/manual/ust.html

原创粉丝点击