本文檔介紹了Linux核心中的追蹤點及其使用方法。文檔中提供的例子詳細說明了如何在核心中插入追蹤點,如何將探測函數與追蹤點聯絡起來。同時也提供了一些探測函數的例子。
Ø 追蹤點的目的
代碼中的追蹤點提供了在運行時調用探測函數的鉤子。追蹤點可以開啟(已串連探測函數)或關閉(沒有串連探測函數)。處於關閉狀態的追蹤點不會引發任何效果,除了增加了一點時間開銷(檢查一條分支語句的條件)和空間開銷(在instrumented function[不知道如何翻譯合適]的尾部增加幾條函數調用的代碼,在獨立地區增加一個資料結構)。如果一個追蹤點被開啟,那麼每次追蹤點被執行時都會調用串連的探測函數,而且在調用者的執行內容中。探測函數執行結束後,將返回到調用者(從追蹤點繼續執行)。
可以在代碼中的重要位置安放追蹤點。它們是輕量級的鉤子函數,能夠傳遞任意個數的參數,原型可以在定義追蹤點的標頭檔中找到。
追蹤點可以用來進行系統追蹤並進行效能統計。
Ø 使用方法
每個追蹤點都包含2個元素:
-
追蹤點定義。位於標頭檔中。
-
追蹤點聲明。位於C檔案中。
使用追蹤點時,需要包含標頭檔linux/tracepoint.h.
例如,在檔案[include/trace/subsys.h]中:
#include <linux/tracepoint.h>
DECLARE_TRACE(subsys_eventname,
TP_PROTO(int
firstarg, struct task_struct *p),
TP_ARGS(firstarg,
p));
在檔案[subsys/file.c](添加追蹤聲明的地方)中:
#include <trace/subsys.h>
DEFINE_TRACE(subsys_eventname);
void somefct(void)
{
...
trace_subsys_eventname(arg,
task);
...
}
在代碼中:
-
subsys_eventname是被追蹤事件的描述符。
-
subsys是子系統的名字。
-
eventname是待追蹤事件的名字。
-
TP_PROTO(int firstarg, struct
task_struct *p)是此追蹤點調用的探測函數的原型。
-
TP_ARGS(firstarg, p)表示參數的名稱,與原型中的相同。
通過函數register_trace_subsys_eventname()可以為追蹤點綁定探測函數。而unregister_trace_subsys_eventname()則可以移除一個探測函數。
在模組的推出函數中必須調用tracepoint_synchronize_unregister(),以確保沒有代碼繼續使用這個探測函數。這個操作,再加上在探測函數附近禁止搶佔,可以保證探測函數的移除與模組的卸載是安全的。
追蹤點機制允許插入同一個追蹤點的多個執行個體。但是任何一個追蹤點的名字在整個核心中都必須是唯一的,否則就可能會發生類型衝突。可以使用原型追蹤點的名稱重整[name mangling],這樣可以保證類型的正確性。對探測函數的類型正確性的驗證由編譯器在探測函數註冊時進行。追蹤點可以位於內嵌函式、內聯靜態函數、unrolled迴圈以及常規的函數中。
我們推薦使用名稱架構“subsys_event”,這會有效地限制住衝突。追蹤點名稱在核心中是全域變數:無論在核心核心映像中,還是在模組中,相同名稱的追蹤點都被認為是同一個追蹤點。
如果追蹤點必須在核心模組中使用,可以使用EXPORT_TRACEPOINT_SYMBOL_GPL()或EXPORT_TRACEPOINT_SYMBOL()匯出這些追蹤點。
Ø 探測/追蹤點執行個體
參考在samples/tracepoints中提供的例子。
需要與核心一起編譯它們。如果選項CONFIG_SAMPLE_TRACEPOINTS=m,這些樣本將在執行make操作時被編譯(而不是’make
modules’).
以root身份進入系統:
modprobe tracepoint-sample (insmod order is not important)
modprobe tracepoint-probe-sample
cat /proc/tracepoint-sample (returns an expected error)
rmmod tracepoint-sample tracepoint-probe-sample
dmesg