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");
相關文章
相關標籤/搜索