tracepoint你真的了解吗?

前言

很惭愧,搞了这么久的linux开发,以前测试不管是用ftrace仍是perf也好,都没有认真的去了解tracepoint的实现,此次正好linux

开发的代码中须要设计一个tracepoint,便于后期调试使用,因此趁此机会,了解下tracepoint在内核里面的编写。ide

你真的知道trace的原理吗?

这里大体介绍下tracepoint的大体原理,和kprobe相比,tracepoint是一个安静的乖孩子,只有在内核里面编写好才能使用函数

而kprobe不同,可动可静,是一个活力十足的假小子,tracepoint实现是基于hooks的思想,function trace是利用gcc编译器初期测试

在函数的入口就被放置一个probe点,也俗称打桩,这个probe点就会跟踪调用这个函数的各类信息,例如进程,地址,栈信息等,debug

并将追踪的信息保存到一个环形队列中去,若是用户但愿读取这些内核,就会经过debugfs形式来访问,因此有时候我在想是否是能够设计

写一个程序,去专门监控trace环形队列占用的内存状况(有点跑偏了),下面从网上找的一张图介绍下这个trace的调用流程。调试

 

去实现一个tracepoint

实现一个tracepoint是很简单的事,尤为是有经验的内核开发同窗,你只须要看下Documentation/trace/相关文档介绍,在看看blog

内核里面任何一个tracepoint的实现patch, 基本就能够照葫芦画瓢去弄了,至少我在写tracepoint的时候就是这么弄的,颇有意思。队列

step1: 实现一个tracepoint的头文件

咱们须要定义一个tracepint的头文件,最好和你想要跟踪的function所在的目录或者相关头文件放在一块儿。进程

例如我这里定义trace_myself.h文件

// trace_myself.h
#undef TRACE_SYSTEM #define TRACE_SYSTEM myself
#if !defined(__TRACE_MYSELF_H__) || defined(TRACE_HEADER_MULTI_READ)

#define __TRACE_MYSELF_H__#include <linux/tracepoint.h> // 此处是很是关键的地方,设计到你要追踪的函数的的相关内容做为参数// 为了方便,这里将参数设置为unsiged short形式TRACE_EVENT(myself_tp,
    TP_PROTO(unsigned short dest, unsigned short source),
    TP_ARGS(dest, source), // 定义两参数名称为dest和source
    TP_STRUCT__entry(  // 此处本人理解为打桩时候分配的环形队列时指定的做用域,说白了就是大小和attr。
        __field(unsigned short, dest)
        __field(unsigned short, source)
    ),
TP_fast_assign(
    __entry->dest = dest;   //  将trace的函数的内容拷贝到环形队列中去
    __entry->source = source;
),

TP_printk("dest:%d, source:%d", __entry->dest, __entry->source)  // 打印你所指望的内容
);

#endif // 此处定义完成后,仅仅是类型定义成功

// 下一步咱们须要指定头文件所在的目录,而且定义头文件的名称
#undef TRACE_INCLUDE_PATH #define TRACE_INCLUDE_PATH . #define TRACE_INCLUDE_FILE trace_myself // 这就是该头文件的名字 #include <trace/define_trace.h>

到这一步,只能算是你tracepoint function实现了,可是怎么编译和在代码中添加,又有不少规则须要注意

step2: 加入到makefile中去

ccflags-y += -I$(src)   # needed for trace events

就是这么简短的一句,可是非加不可,若是不加,可定是不行的,gcc编译的时候会查找相关头文件,这告诉编译器,此处的头文件也要包含。

step3: 在trace里的函数加入tracepoint


//此处须要知道的是trace的函数所在的文件里必须包含CREATE_TRACE_POINTS
//而且必须在头文件以前,虽然不理解,可是仍是的遵照

#define CREATE_TRACE_POINTS
#include "test_tp.h" #include <net/protocol.h> #include <linux/ip.h> #include <linux/udp.h> int test(unsiged short dst, unsiged short src) { dst = src + 5;// 这里增长一个tracepoint点 trace_myself(dst, src);
return 0; } int init_module(void) { int ret = 0, dest = 5, src = 5;
ret = test(dest, src); if (ret) { printk("failed\n"); return ret; } return 0; }
void cleanup_module(void) {
  printk("failed\n");
} int init_module(void); void cleanup_module(void); MODULE_LICENSE("GPLv2");
相关文章
相关标签/搜索