摘要:和很多l(xiāng)inux內(nèi)核子系統(tǒng)一樣,static tracepoint有很多層次,其中某個層次都展示給不同層次的開發(fā)者來滿足他們的不同需求。關于linux tracepoint的詳細信息,我們可以在linux內(nèi)核文檔Documentation/trace/tracepoints.txt和 samples/tracepoints這兩個地方找到。大致來說,對tracepoints本身的定義是第一個層次,一般只有內(nèi)核開發(fā)者才會定義這些tracepoints;trace event是第二個層次,用于debug;第三個層次就是perf這些內(nèi)核測試工具,他們調(diào)用底層的trace events來監(jiān)控系統(tǒng)內(nèi)核的某些特性。 一個tracepoint可以理解為一個linux內(nèi)核中的占位符函數(shù),內(nèi)核子系統(tǒng)的開發(fā)者常常用它們來debug。static表明這些tracepoint的位置是固定的,你可以把它理解位傳統(tǒng)C程序中的 #if DEBUG部分。如果在運行時沒有開啟,它們是不占用任何系統(tǒng)開銷的。本文主要為你講解如何用ftrace來使用這些tracepoint,當然,你也可以使用perf來使用這些tracepoints。 本文來源:
所有這些靈活性也有一定的缺點。一個可執(zhí)行的kprobe有一個顯著的負載——因為它利用了breakpoints和exception hadlers。另一個方面是probe的放置地點:kprobes可以很方便的放置在函數(shù)入口或者出口,但是如果你需要把probe放置在函數(shù)內(nèi)部或者需要probe局部變量,那么你就需要systemtap和配置了 CONFIG_DEBUG_INFO的自己編譯的內(nèi)核。 從這個角度上看,靜態(tài)tracepoints可以被放置在函數(shù)的任意地方,而且可以越過任意重要的局部變量。linux 2.6.32的主線以后已經(jīng)實現(xiàn)了比較多的靜態(tài)tracepoint。 增加一個靜態(tài)tracepoint是非常簡單的,你可以參考這個例子。在這個例子中,我給已經(jīng)存在的trace組(irq)增加tracepoint,所以我僅僅需要定義tracepoint和這些tracepoints。你可以在內(nèi)核的文檔linux/samples/trace_events/trace-events-sample.h中找到一個tracepoint定義的五個部分的解釋。針對更加復雜的例子,可以參考linux/samples/trace_events/。
2.使用linux static tracepoint
2.1掛載debug文件系統(tǒng) mount -t debugfs nodev /debug
2.2查看可供使用的tracepoints # cat /sys/kernel/debug/tracing/available_events skb:skb_copy_datagram_iovec skb:kfree_skb block:block_rq_remap block:block_remap block:block_split block:block_unplug_io block:block_unplug_timer Since we added our tracepoints to the irq group, we can find them in tracing/events/irq: # ls /sys/kernel/debug/tracing/events/irq/ enable irq_handler_entry softirq_entry tasklet_entry filter irq_handler_exit softirq_exit tasklet_exit Enable the tasklet tracepoints: # echo 1 > /sys/kernel/debug/tracing/events/irq/tasklet_entry/enable # echo 1 > /sys/kernel/debug/tracing/events/irq/tasklet_exit/enable And the output is available in the trace buffer: # cat /sys/kernel/debug/tracing/trace # tracer: nop # # TASK-PID CPU# TIMESTAMP FUNCTION # | | | | | -0 [000] 327.349213: tasklet_entry: func=.rpavscsi_task -0 [000] 327.349217: tasklet_exit: func=.rpavscsi_task When finished, we can disable the tracepoints. There are enable files at all levels of the hierarchy, so we can disable all tracepoints in one go: # echo 0 > /sys/kernel/debug/tracing/events/enable
3.在內(nèi)核模塊中使用靜態(tài)tracepoints
Kernel modules can also make use of static tracepoints. A simple module that hooks the tasklet_entry tracepoint and printks the function name of the tasklet might look like (I’ve called it tracepoint-example.c):
static void __exit trace_exit(void)
4 利用ftrace跟蹤static tracepoints
以下所有操作均在/debug/tracing目錄下進行 大致的步驟為:設定要監(jiān)控的event,實際上也就是要監(jiān)控的一系列的tracepoints;設定tracer成nop;開啟tracing_on;查看結果。
4.1 使用event有兩種方式
i) 通過set_event文件 events被組織成一個個子系統(tǒng),如ext4,irq,sched等待,一個完整的event name是這樣的:<subsystem>:<event>,其中subsystem是可選的,一個子系統(tǒng)中所有的events可以通過<subsystem>:*指定。
ii) 通過'enable' toggle
實例:我們需要監(jiān)控writeback子系統(tǒng),那么需要進行如下設定 $:echo writeback > set_event
4.2開啟監(jiān)控 $:echo nop > current_tracer $:echo 1 > tracing_on (wait for a moment......)
4.3結果查看:event trace的意義
$:cat trace | head -20 輸出結果如下:
關于輸出結果的意義,可以到對應events下面,利用cat fromat查看輸出格式和意義
這里,不以common_開頭的filed是每個event特有的。每一個event對應的有一個TRACE_EVENT定義一個record,這里offset為field在record中的偏移,size為其大小。下載一個內(nèi)核,在samples/trace_events目錄下有一個例子,可以查看TRACE_EVENT的定義方法。
4.4event filter 語法:
可以通過'&&', '||',以及圓括號將幾個predicate組合起來。對于數(shù)字域,可以使用操作符==, !=, < , > , <=, >=,對于字符串域,可以使用==, !=。目前字符串只支持完全匹配,且最多可以組合16個predicate。 例子:
每個子系統(tǒng)都有獨立的filter文件支持,如:
可以看到,雖然將sched子系統(tǒng)的filter設為prev_pid == 0,但由于只有sched_switch事件存在prev_pid域,所以對sched的filter文件的設置只影響了sched_switch。
4.5定義一個event-enabled tracepoint 定義tracepoint不在本文討論范圍之內(nèi)
參考文檔:
【1】Linux Static Tracepoints 【2】 【3】ftrace 學習筆記: 【4】tracing on linux |
|
來自: 寫意人生 > 《調(diào)試方法》