利用ftrace跟蹤內核static tracepoint

摘要:和不少linux內核子系統同樣,static tracepoint有不少層次,其中某個層次都展現給不一樣層次的開發者來知足他們的不一樣需求。關於linux tracepoint的詳細信息,咱們能夠在linux內核文檔Documentation/trace/tracepoints.txt和 samples/tracepoints這兩個地方找到。大體來講,對tracepoints自己的定義是第一個層次,通常只有內核開發者纔會定義這些tracepoints;trace event是第二個層次,用於debug;第三個層次就是perf這些內核測試工具,他們調用底層的trace events來監控系統內核的某些特性。node

一個tracepoint能夠理解爲一個linux內核中的佔位符函數,內核子系統的開發者經常用它們來debug。static代表這些tracepoint的位置是固定的,你能夠把它理解位傳統C程序中的 #if DEBUG部分。若是在運行時沒有開啓,它們是不佔用任何系統開銷的。本文主要爲你講解如何用ftrace來使用這些tracepoint,固然,你也可使用perf來使用這些tracepoints。linux

本文來源:
1.什麼是linux static tracepointbash

 

 

       全部這些靈活性也有必定的缺點。一個可執行的kprobe有一個顯著的負載——由於它利用了breakpoints和exception hadlers。另外一個方面是probe的放置地點:kprobes能夠很方便的放置在函數入口或者出口,可是若是你須要把probe放置在函數內部或者須要probe局部變量,那麼你就須要systemtap和配置了 CONFIG_DEBUG_INFO的本身編譯的內核。 從這個角度上看,靜態tracepoints能夠被放置在函數的任意地方,並且能夠越過任意重要的局部變量。linux 2.6.32的主線之後已經實現了比較多的靜態tracepoint。函數

        增長一個靜態tracepoint是很是簡單的,你能夠參考這個例子。在這個例子中,我給已經存在的trace組(irq)增長tracepoint,因此我僅僅須要定義tracepoint和這些tracepoints。你能夠在內核的文檔linux/samples/trace_events/trace-events-sample.h中找到一個tracepoint定義的五個部分的解釋。針對更加複雜的例子,能夠參考linux/samples/trace_events/。工具

 

2.使用linux static tracepoint學習

 

2.1掛載debug文件系統測試

mount -t debugfs nodev /debugspa

 

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_timerdebug

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.在內核模塊中使用靜態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):

 


#include <linux/interrupt.h>
#include <linux/module.h>
#include <trace/events/irq.h>
static void probe_tasklet_entry(struct tasklet_struct *t)
{
printk("tasklet_entry %pf\n", t->func);
}
static int __init trace_init(void)
{
WARN_ON(register_trace_tasklet_entry(probe_tasklet_entry));
return 0;
}

static void __exit trace_exit(void)
{
unregister_trace_tasklet_entry(probe_tasklet_entry);
}
module_init(trace_init)
module_exit(trace_exit)
MODULE_LICENSE("GPL");

 

4 利用ftrace跟蹤static tracepoints

 

如下全部操做均在/debug/tracing目錄下進行

大體的步驟爲:設定要監控的event,實際上也就是要監控的一系列的tracepoints;設定tracer成nop;開啓tracing_on;查看結果。

 

4.1 使用event有兩種方式

 

i) 經過set_event文件

events被組織成一個個子系統,如ext4,irq,sched等待,一個完整的event name是這樣的:<subsystem>:<event>,其中subsystem是可選的,一個子系統中全部的events能夠經過<subsystem>:*指定。

 

 

  • #echo *:* > set_event
  • #echo 'irq:*' > set_event

 

 

ii) 經過'enable' toggle

 

 

 

實例:咱們須要監控writeback子系統,那麼須要進行以下設定

$:echo writeback > set_event

 

 

 

 

4.2開啓監控

$:echo nop > current_tracer

$:echo 1 > tracing_on

(wait for a moment......)

 

 

4.3結果查看:event trace的意義

 

$:cat trace | head -20 

輸出結果以下:

 

利用ftrace跟蹤內核static tracepoint

 

 

 

關於輸出結果的意義,能夠到對應events下面,利用cat fromat查看輸出格式和意義

利用ftrace跟蹤內核static tracepoint

 

這裏,不以common_開頭的filed是每一個event特有的。每個event對應的有一個TRACE_EVENT定義一個record,這裏offset爲field在record中的偏移,size爲其大小。下載一個內核,在samples/trace_events目錄下有一個例子,能夠查看TRACE_EVENT的定義方法。

 

4.4event filter

語法:

 

  • field-name relation-operatior value                           //一個predicate

 

能夠經過'&&', '||',以及圓括號將幾個predicate組合起來。對於數字域,可使用操做符==, !=, < , > , <=, >=,對於字符串域,可使用==, !=。目前字符串只支持徹底匹配,且最多能夠組合16個predicate。

例子:

 

 

  • #cd /sys/kernel/debug/tracing/events/signal/signal_generate
  • #echo "((sig >= 10 && sig < 15) || sig == 17) && comm != bash" > filter

 

 

每一個子系統都有獨立的filter文件支持,如:

 

 

 

能夠看到,雖然將sched子系統的filter設爲prev_pid == 0,但因爲只有sched_switch事件存在prev_pid域,因此對sched的filter文件的設置隻影響了sched_switch。

 

 

4.5定義一個event-enabled tracepoint

定義tracepoint不在本文討論範圍以內

 


參考文檔:

 

【1】Linux Static Tracepoints    【2】 

【3】ftrace 學習筆記:

【4】tracing on linux  

相關文章
相關標籤/搜索