Linux Trace Toolkit

来源:互联网 发布:java跨平台原理 编辑:程序博客网 时间:2024/06/06 08:51

1 概念

1.1 功能

LTT是一个用于跟踪系统详细运行状态和流程的工具,它可以跟踪记录系统中的特定事件。这些事件包括:

 系统调用的进入和退出
 陷阱/中断(Trap / Irq)的进入和退出
 进程调度事件
 内核定时器
 进程管理相关事件:创建 ,唤醒,信号处理等等
 文件系统相关事件:Open / Read / Write / Seek / Ioctl 等等
 内存管理相关事件:内存分配/释放等
 其他事件:IPC / Socket/ 网络 等等

此外 Ltt还提供了自定义和记录需要跟踪的事件类型的函数接口。

1.2 结构

LTT主要由4个部分组成:
 内核代码补丁:LTT目前还没有纳入正式的官方内核,在内核中的部分代码需要打Patch来获得,主要是修改了上述各类事件的相关代码,添加了Trace的调用代码
 内核模块:Trace功能的主要实现部分,记录内核事件,并和用户空间的守护进程进行交互
 用户空间的守护进程:从LTT的内核模块中获取事件相关数据,并写入文件。
 数据分析应用程序:读取守护进程生成的数据文件,加以分析,并以更加可读的方式(图表等)显示出来。
 

 除此之外,LTT还具备自定义和跟踪用户空间事件的能力。

2 使用

    所有的安转使用相关的内容,都可以在LTT的官方站点:http://www.opersys.com/ltt/ 找到。仔细阅读里面的文档即可。 
(不过,其稳定版本在我这编译起来居然有Error,修改过一些代码后,编译通过,有很多warning,或许是我的编译环境有问题,最终试用的时候图省事,没有去过多研究,使用了Montavista的Package中现成编译好的版本 8 )

3 体会

LTT的确是一个很有用的工具,灵活的配合其他工具的使用,如strace,time等等,可以作为分析优化系统的performance的一个可行的途径。

值得一提的是,LTT可以通过设置参数,在特定的时间段,筛选所需要记录的事件类型,还可以按进程ID等选择所跟踪的特定对象,通过合理的配置参数,可以使得其对系统所造成的额外负担减少到一个合理的程度,对系统性能的分析基本不会造成明显的干扰因素。

另外LTT提供的自定义和记录需要跟踪的事件类型的函数接口,也使它有了一些拓展能力,可以用来Debug自己编写的内核模块代码。

LTT跟踪用户空间事件的实现,是通过其内核模块中几个特定的IOCTL接口,由用户空间的一个LIB库将其包装成函数,使得其使用方法与其在内核模块中自定义和记录事件类型的函数接口相同。应该说这是一个很巧妙的实现办法,不过对其性能个人还是有些怀疑,因为这样一来,对用户空间事件的纪录就需要经由 用户空间-〉内核空间-〉用户空间 走一趟来实现。


inux trace toolkit 并不像strace那样,stace一般都只是针对一个程序的跟踪,不过,linux trace toolkit是用来对整个系统的性能进行trace的工具,这个需要kernel的支持,因此,一般都要对kernel打ltt的补丁。LTT支持的kernel相关的一些event的trace,所谓的trace point即能够被trace的地方:

Table 9.1. Trace Points for the Kernel

Event Type

Event Subtype

Event Details

System call entry

N/A

System call ID, instruction counter

System call exit

N/A

None

Trap entry

N/A

Trap ID, instruction counter

Trap exit

N/A

None

Interrupt entry

N/A

Interrupt ID, kernel-space occurrence

Interrupt exit

N/A

None

Scheduling change

N/A

Incoming process ID, outgoing process ID, outgoing process state

Kernel timer

N/A

None

Soft IRQ

Bottom half

Bottom half ID

 

Soft IRQ

Bottom half ID

 

Tasklet action

Address of function

 

Tasklet hi-action

Address of function

Process

Creation of kernel thread

Thread start address, PID

 

Fork or clone

PID of created process

 

Exit

None

 

Wait

PID waited on

 

Signal

Signal ID, destination PID

 

Wakeup

Process PID, state prior to wakeup

File system

Starting to wait for a data buffer

None

File system

End to the wait for a data buffer

None

 

An exec occurred

Filename

 

An open occurred

Filename, file descriptor

 

A close occurred

File descriptor

 

A read occurred

File descriptor, amount read

 

A write occurred

File descriptor, amount written

 

A seek occurred

File descriptor, offset

 

An ioctl occurred

File descriptor, command

 

A select occurred

File descriptor, timeout

 

A poll occurred

File descriptor, timeout

Timer

Timer expired

None

 

Setting itimer occurred

Type, time

 

Setting schedule timeout occurred

Time

Memory

Page allocated

Size order

 

Page freed

Size order

 

Swap in

Page address

 

Swap out

Page address

 

Page wait start

None

 

Page wait end

None

Socket

Socket call has occurred

Call ID, socket ID

 

Socket has been created

Socket type, ID of created socket

 

Data has been sent to a socket

Socket type, amount sent

 

Data has been read for a socket

Socket type, amount received

Interprocess communication

System V IPC call

Call ID, object ID

 

Message queue has been created

Message queue ID, creation flags

 

Semaphore has been created

Semaphore ID, creation flags

 

Shared memory segment has been created

Shared memory ID, creation flags

Network

Incoming packet

Protocol type

 

Outgoing packet

Protocol type

 

   LTT使用了relayFS技术,这个与proc fs 有点类似,即将kernel的一些信息供用户空间方便的使用,但是有个重要的区别,就是,relayFS旨在提供kernel与user space之间高效快速的大量数据传输的情况。关于relayFS的资料,如下,转载自:

http://www.yuanma.org/data/2006/0927/article_1607.htm

从Linux-2.6.14内核(2.6.12需要打补丁,2.6.13的内核手头没有,不知道)开始,relayfs开始作为内核中File System选项中伪文件系统(Pseudo File System)来出现,这是一个新特性。
  File System--->
    Pseudo filesystems---->
        <>Relayfs File System Support
  我们知道,Pseduo File System 另外一个很有名的东西是Proc File System,几乎每个学习Linux的都知道使用这个文件系统来查看cpu型号,内存容量等等其它很多的runtime information。Proc FS为users提供了一个方便的接口来查询很多只有内核才能查看的信息,比如:cpuinfo,meminfo,interrupts等等,这些都只是 kernel管理的对象,但是我们可以以一个普通users的身份也可以查看,proc FS将内核信息可以动态地传递出来,供普通的process随时查看,某些情况下,用户也可以将信息传递到内核空间,比如:echo 1>/proc/sys/net/ipv4/ip_forward。同样地,relayfs也是可以一种内核和用户空间交换数据的工具,不同的是,它支持大容量的数据交换。
    relayfs中有一个很重要的概念叫做”channel“,具体来说,一个channel就是由很多个内核的buffer组成的一个集合,这些内核的buffer在relayfs中就体现为一个个的文件。 当kernel中的程序把数据写入某个channel时,这些数据实际上自动填入这些channel的buffer。 用户空间的应用程序mmap()将relayfs中的这些文件做个映射,然后在适当的时候把数据提取出来。
    写入channel的数据格式完全取决于最终从channel中提取数据的程序,relayfs可以提取一些hook程序,这些hook程序允许relayfs的数据提取程序(relayfs的客户端)为buffer中的数据增加一些数据结构。这个过程,就像解码跟编码的关系一样,你使用的编码程序和解码程序只有对应就可以,与传输程序无关,当然,你在传输的同时也可以对它进行一些编码,但是这些取决于你最终的解码。 但是,relayfs不提供任何形式的数据过滤,这些任务留给relayfs客户端去完成。 relayfs的设计目标就是尽可能地简单。
    每一个relayfs channel都有一个buffer(单CPU情况),每一个buffer又有一个或者多个二级buffer。 消息是从第一个二级buffer开始写入的,直到这个buffer满为止。然后如果第二个二级buffer可用,就写入第二个二级部分反而,一次类推。 所以,如果第一个二级buffer被填满,那么就会通知用户空间,同时,kernel就会去写第二个二级buffer。
    如果kernel发出通知说一个二级buffer被填满了,那么kernel肯定知道填了多少字节。userspace根据这个数字就可以仅仅拷贝合法的数据。拷贝完毕,userpsace通知kernel说一个二级buffer已经被使用了。
    relayfs采用这么一种模式,它会直接去覆盖数据即使这些数据还没有被userspace所收集。(一个问题,如何保持传输的完整性,目前我也不知道)
    下面说说relayfs的user space API:
    relayfs为了使得空间程序可以访问channel里面的buffer数据,实现了基本的文件操作。文件操作函数如下:
    open 打开一个存在的buffer
    mmap 可以使得channel的buffer被映射到调用函数的内存空间,注意,你不能部分映射,而是要映射整个文件。
    reald   读取channel buffer的内容
    poll     通知用户空间程序二级buffer空间已满
    close   关闭

    为了使得用户空间的程序可以使用relayfs文件,relayfs必须被mount,格式跟proc差不多,like this:
    mount -t relayfs relayfs /mnt/relay/

    下面是kernel空间的一些API:
        relay_open(base_filename, parent, subbuf_size, n_subbufs, callbacks)
        relay_close(chan)
        relay_flush(chan)
        relay_reset(chan)
        relayfs_create_dir(name, parent)
        relayfs_remove_dir(dentry)
        relayfs_create_file(name, parent, mode, fops, data)
        relayfs_remove_file(dentry)
        relay_subbufs_consumed(chan, cpu, subbufs_consumed)
        relay_write(chan, data, length)
        __relay_write(chan, data, length)
      relay_reserve(chan, length)
      subbuf_start(buf, subbuf, prev_subbuf, prev_padding)
      buf_mapped(buf, filp)
      buf_unmapped(buf, filp)
      create_buf_file(filename, parent, mode, buf, is_global)
      remove_buf_file(dentry)


http://www.opersys.com/ltt/

http://lttng.org/

0 0
原创粉丝点击