linux性能工具--ftrace使用

Ftrace設計作爲一個內部的tracer提供給系統的開發者和設計者,幫助他們弄清kernel正在發生的行爲,它能夠調式分析延遲和性能問題。對於前一章節,我們學習了Ftrace發展到現在已經不僅僅是作爲一個function tracer了,它實際上成爲了一個通用的trace工具的框架

  • 一方面已經從function tracer擴展到irqsoff tracer、preemptoff tracer
  • 另一方面靜態的trace event也成爲trace的一個重要組成部分

通過前面兩節的學習,我們知道了什麼是ftrace,能夠解決什麼問題,從這章開始我們主要是學習,怎麼去使用ftreace解決問題。

1 ftrace基礎用法

ftrace 通過 debugfs 向用戶態提供訪問接口。配置內核時激活 debugfs 後會創建目錄 /sys/kernel/debug ,debugfs 文件系統就是掛載到該目錄。要掛載該目錄,需要將如下內容添加到 /etc/fstab 文件:

debugfs  /sys/kernel/debug  debugfs  defaults  0  0 1

或者可以在運行時掛載:

mount  -t  debugfs  debugfs  /sys/kernel/debug

激活內核對 ftrace 的支持後會在 debugfs 下創建一個 tracing 目錄 /sys/kernel/debug/tracing 。該目錄下包含了 ftrace 的控制和輸出文件

root@100ask:/sys/kernel/debug/tracing# ls
available_events events README snapshot trace_pipe
available_filter_functions free_buffer saved_cmdlines stack_max_size trace_stat
available_tracers function_profile_enabled saved_cmdlines_size stack_trace tracing_cpumask
buffer_percent hwlat_detector saved_tgids stack_trace_filter tracing_max_latency
buffer_size_kb instances set_event synthetic_events tracing_on
buffer_total_size_kb kprobe_events set_event_pid timestamp_mode tracing_thresh
current_tracer kprobe_profile set_ftrace_filter trace uprobe_events
dynamic_events max_graph_depth set_ftrace_notrace trace_clock uprobe_profile
dyn_ftrace_total_info options set_ftrace_pid trace_marker
enabled_functions per_cpu set_graph_function trace_marker_raw
error_log printk_formats set_graph_notrace trace_options

其中重點關注以下文件

  • trace查看選擇器

查看支持的跟蹤器available_tracers

root@100ask:/sys/kernel/debug/tracing# cat available_tracers

hwlat blk mmiotrace function_graph wakeup_dl wakeup_rt wakeup function nop

類型 含義
function 函數調用追蹤器,可以看出哪個函數何時調用,可以通過過濾器指定要跟蹤的函數
function_graph 函數調用圖表追蹤器,可以看出哪個函數被哪個函數調用,何時返回
blk block I/O追蹤器,blktrace用戶應用程序 使用的跟蹤器
mmiotrace MMIO(Memory Mapped I/O)追蹤器,用於Nouveau驅動程序等逆向工程
wakeup 跟蹤進程喚醒信息,進程調度延遲追蹤器
wakeup_rt 與wakeup相同,但以實時進程爲對象
nop 不會跟蹤任何內核活動,將 nop 寫入 current_tracer 文件可以刪除之前所使用的跟蹤器,並清空之前收集到的跟蹤信息,即刷新 trace 文件
wakeup_dl 跟蹤並記錄喚醒SCHED_DEADLINE任務所需的最大延遲(如"wakeup”和"wakeup_rt”一樣)
mmiotrace 一種特殊的跟蹤器,用於跟蹤二進制模塊。它跟蹤模塊對硬件的所有調用
hwlat 硬件延遲跟蹤器。它用於檢測硬件是否產生任何延遲

查看當前的跟蹤器current_tracer ,可以echo選擇

root@100ask:/sys/kernel/debug/tracing# cat current_tracer

nop

  • trace使能

tracing_on :是否往循環buffer寫跟蹤記錄,可以echo設置

root@100ask:/sys/kernel/debug/tracing# cat tracing_on

1

  • trace過濾器選擇(可選)

    • set_ftrace_filter/set_graph_notrace:(function跟蹤器)函數過濾器,echo xxx設置要跟蹤的函數,

      root@100ask:/sys/kernel/debug/tracing# cat set_ftrace_filter

      all functions enabled

  • trace數據讀取

    • trace:可以cat讀取跟蹤記錄的buffer內容(查看的時候會臨時停止跟蹤)
    • trace_pipe:類似trace可以動態讀取的流媒體文件(差異是每次讀取後,再讀取會讀取新內容)

所以對於ftrace的三步法爲:

  • 1 設置tracer類型
  • 2 設置tracer參數
  • 3 使能tracer

1.2 function trace實例

function,函數調用追蹤器, 跟蹤函數調用,默認跟蹤所有函數,如果設置set_ftrace_filter, 則跟蹤過濾的函數,可以看出哪個函數何時調用。

  • available_filter_functions:列出當前可以跟蹤的內核函數,不在該文件中列出的函數,無法跟蹤其活動

  • enabled_functions:顯示有回調附着的函數名稱。

  • function_profile_enabled:打開此選項,在trace_stat中就會顯示function的統計信息。

  • set_ftrace_filter:用於指定跟蹤的函數

  • set_ftrace_notrace:用於指定不跟蹤的函數

  • set_ftrace_pid:用於指定要跟蹤特定進程的函數

Disable tracer:

echo 0 > tracing_on

設置 tracer 類型爲 function:

echo function > current_tracer

set_ftrace_filter 表示要跟蹤的函數,這裏我們只跟蹤 dev_attr_show 函數:

echo dev_attr_show > set_ftrace_filter

Enable tracer:

echo 1 > tracing_on

提取trace結果:

從上圖可以看到 function trace 一個函數的方法基本就是三板斧:

  • 設置 current_tracer 爲 function
  • 設置要 trace 的函數
  • 打開 trace 開關,開始 trace
  • 從 trace 信息我們可以獲取很多重要信息:
  • 進程信息,TASK-PID,對應任務的名字
  • 進程運行的 CPU
  • 執行函數時的系統狀態,包括中斷,搶佔等狀態信息
  • 執行函數的時間輟,字段 TIMESTAMP 是時間戳,其格式爲“.”,表示執行該函數時對應的時間戳
  • FUNCTION 一列則給出了被跟蹤的函數,函數的調用者通過符號 “<-” 標明,這樣可以觀察到函數的調用關係。

function 跟蹤器可以跟蹤內核函數的調用情況,可用於調試或者分析 bug ,還可用於瞭解和觀察 Linux 內核的執行過程。同時ftrace允許你對一個特定的進程進行跟蹤,在/sys/kernel/debug/tracing目錄下,文件set_ftrace_pid的值要更新爲你想跟蹤的進程的PID。

echo $PID > set_ftrace_pid

1.3 function_graph Trace 實例

function_graph 跟蹤器則可以提供類似 C 代碼的函數調用關係信息。通過寫文件 set_graph_function 可以顯示指定要生成調用關係的函數,缺省會對所有可跟蹤的內核函數生成函數調用關係圖。

函數圖跟蹤器對函數的進入與退出進行跟蹤,這對於跟蹤它的執行時間很有用。函數執行時間超過10微秒的標記一個“+”號,超過1000微秒的標記爲一個“!”號。通過echo function_graph > current_tracer可以啓用函數圖跟蹤器。

與 function tracer 類似,設置 function_graph 的方式如下:

設置 tracer 類型爲 function_graph:

echo function_graph > current_tracer

set_graph_function 表示要跟蹤的函數:

echo __do_fault > set_graph_function
echo 1 > tracing_on

捕捉到的 trace 內容

我們跟蹤的是 __do_fault 函數,但是 function_graph tracer 會跟蹤函數內的調用關係和函數執行時間,可以協助我們確定代碼執行流程。比如一個函數內部執行了很多函數指針,不能確定到底執行的是什麼函數,可以用 function_graph tracer 跟蹤一下。

  • CPU 字段給出了執行函數的 CPU 號,本例中都爲 1 號 CPU。
  • DURATION 字段給出了函數執行的時間長度,以 us 爲單位。
  • FUNCTION CALLS 則給出了調用的函數,並顯示了調用流程。

1.4 wakeup

wakeup tracer追蹤普通進程從被喚醒到真正得到執行之間的延遲。

1.5 wakeup-rt

non-RT進程通常看平均延遲。RT進程的最大延遲非常有意義,反應了調度器的性能

二,trace event 用法

2.1 trace event 簡介

trace event 就是利用 ftrace 框架,實現低性能損耗,對執行流無影響的一種信息輸出機制。相比 printk,trace event:

  • 不開啓沒有性能損耗
  • 開啓後不影響代碼流程
  • 不需要重新編譯內核即可獲取 debug 信息

2.2 使用實例

上面提到了 function 的 trace,在 ftrace 裏面,另外用的多的就是 event 的 trace,我們可以在 events 目錄下面看支持那些事件:

上面列出來的都是分組的,我們可以繼續深入下去,譬如下面是查看 sched 相關的事件

對於某一個具體的事件,我們也可以查看:

上述目錄裏面,都有一個 enable 的文件,我們只需要往裏面寫入 1,就可以開始 trace 這個事件。譬如下面就開始 trace sched_wakeup 這個事件:

我們也可以 trace sched 裏面的所有事件:

三,高級技巧

查看函數調用棧

查看函數調用棧是內核調試最最基本得需求,常用方法:

  • 函數內部添加 WARN_ON(1)
  • ftrace

trace 函數的時候,設置 echo 1 > options/func_stack_trace 即可在 trace 結果中獲取追蹤函數的調用棧。

以 dev_attr_show 函數爲例,看看 ftrace 如何幫我們獲取調用棧:

#cd /sys/kernel/debug/tracing
#echo 0 > tracing_on
#echo function > current_tracer
#echo schedule > set_ftrace_filter
// 設置 func_stack_trace
#echo 1 > options/func_stack_trace
#echo 1 > tracing_on

如何跟蹤一個命令,但是這個命令執行時間很短

我們可以設置ftrace過濾器控制相關文件:

  • set_ftrace_filter function tracer :只跟蹤某個函數
  • set_ftrace_notrace function tracer :不跟蹤某個函數
  • set_graph_function function_graph tracer :只跟蹤某個函數
  • set_graph_notrace function_graph tracer :不跟蹤某個函數
  • set_event_pid trace event :只跟蹤某個進程
  • set_ftrace_pid function/function_graph tracer :只跟蹤某個進程

如果這時候問:如何跟蹤某個進程內核態的某個函數?

答案是肯定的,將被跟蹤進程的 pid 設置到 set_event_pid/set_ftrace_pid 文件即可。

但是如果問題變成了,我要調試 kill 的內核執行流程,如何辦呢?

因爲 kill 運行時間很短,我們不能知道它的 pid,所以就沒法過濾了。

調試這種問題的小技巧,即 腳本化,這個技巧在很多地方用到:

sh -c "echo $$ > set_ftrace_pid; echo 1 > tracing_on; kill xxx; echo 0 > tracing_on"

如何跟蹤過濾多個進程?多個函數?

  • 函數名雷同,可以使用正則匹配
# cd /sys/kernel/debug/tracing
# echo 'dev_attr_*' > set_ftrace_filter
# cat set_ftrace_filter
dev_attr_store
dev_attr_show
  • 追加某個函數

用法爲:echo xxx >> set_ftrace_filter,例如,先設置 dev_attr_*:

# cd /sys/kernel/debug/tracing
# echo 'dev_attr_*' > set_ftrace_filter
# cat set_ftrace_filter
dev_attr_store
dev_attr_show

再將 ip_rcv 追加到跟蹤函數中:

# cd /sys/kernel/debug/tracing
# echo ip_rcv >> set_ftrace_filter
# cat set_ftrace_filter
dev_attr_store
dev_attr_show
ip_rcv

基於模塊過濾

格式爲:::,例如,過濾 ext3 module 的 write* 函數:

$ echo 'write*:mod:ext3' > set_ftrace_filter

從過濾列表中刪除某個函數,使用“感嘆號”

感嘆號用來移除某個函數,把上面追加的 ip_rcv 去掉:

# cd /sys/kernel/debug/tracing
# cat set_ftrace_filter
dev_attr_store
dev_attr_show
ip_rcv
# echo '!ip_rcv' >> set_ftrace_filter
# cat set_ftrace_filter
dev_attr_store

四,前端工具

我們可以手工操作/sys/kernel/debug/tracing路徑下的大量的配置文件接口,來使用ftrace的強大功能。但是這些接口對普通用戶來說太多太複雜了,我們可以使用對ftrace功能進行二次封裝的一些命令來操作。

trace-cmd就是ftrace封裝命令其中的一種。該軟件包由兩部分組成

  • trace-cmd:提供了數據抓取和數據分析的功能
  • kernelshark:可以用圖形化的方式來詳細分析數據,也可以做數據抓取

4.1 trace-cmd

下載編譯ARM64 trace-cmd方法:

git clone [https://github.com/rostedt/trace-cmd.git](https://github.com/rostedt/trace-cmd.git)
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64
make

先通過 record 子命令將結果記錄到 trace.dat,再通過 report 命令進行結果提取。命令解釋:

  • -p:指定當前的 tracer,類似 echo function > current_tracer,可以是支持的 tracer 中的任意一個
  • -l:指定跟蹤的函數,可以設置多個,類似 echo function_name > set_ftrace_filter
  • --func-stack:記錄被跟蹤函數的調用棧

在很有情況下不能使用函數追蹤,需要依賴 事件追蹤 的支持,例如:

4.2 kernelshark圖形化分析數據

trace-cmd report主要是使用統計的方式來找出熱點。如果要看vfs_read()一個具體的調用過程,除了使用上一節的trace-cmd report命令,還可以使用kernelshark圖形化的形式來查看,可以在板子上使用trace-cmd record 記錄事件,把得到的trace.data放到linux 桌面系統,用kernelshark打開,看到圖形化的信息

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章