使用 ftrace 調試 Linux 內核,第 1 部分

概述

ftrace 是 Linux 內核中提供的一種調試工具。使用 ftrace 可以對內核中發生的事情進行跟蹤,這在調試 bug 或者分析內核時非常有用。本系列文章對 ftrace 進行了介紹,分爲三部分。本文是第一部分,介紹了內核相關的編譯選項、用戶態訪問 ftrace 的接口、ftrace 的數據文件,並對 ftrace 提供的跟蹤器的用途進行了介紹,以使讀者更好的瞭解和使用該工具。
ftrace 是內建於 Linux 內核的跟蹤工具,從 2.6.27 開始加入主流內核。使用 ftrace 可以調試或者分析內核中發生的事情。ftrace 提供了不同的跟蹤器,以用於不同的場合,比如跟蹤內核函數調用、對上下文切換進行跟蹤、查看中斷被關閉的時長、跟蹤內核態中的延遲以及性能問題等。系統開發人員可以使用 ftrace 對內核進行跟蹤調試,以找到內核中出現的問題的根源,方便對其進行修復。另外,對內核感興趣的讀者還可以通過 ftrace 來觀察內核中發生的活動,瞭解內核的工作機制。

讓內核支持 ftrace

使用 ftrace ,首先要將其編譯進內核。內核源碼目錄下的 kernel/trace/Makefile 文件給出了 ftrace 相關的編譯選項。
清單 1. ftrace 相關的配置選項列表
CONFIG_FUNCTION_TRACER 
CONFIG_FUNCTION_GRAPH_TRACER 
CONFIG_CONTEXT_SWITCH_TRACER 
CONFIG_NOP_TRACER 
CONFIG_SCHED_TRACER 
...
ftrace 相關的配置選項比較多,針對不同的跟蹤器有各自對應的配置選項。不同的選項有不同的依賴關係,內核源碼目錄下的 kernel/trace/Kconfig 文件描述了這些依賴關係。讀者可以參考 Makefile 文件和 Kconfig 文件,然後選中自己所需要的跟蹤器。
通常在配置內核時,使用 make menuconfig 會更直觀一些。以 2.6.33.1 版本的內核爲例,要將 ftrace 編譯進內核,可以選中 Kernel hacking (圖 1 )下的 Tracers 菜單項(圖 2 )。
圖 1. Kernel hacking

圖 2. Tracers

進入 Tracers 菜單下,可以看到內核支持的跟蹤器列表。如圖 3 所示,這裏選中了所有的跟蹤器,讀者可以根據自己的需要選中特定的跟蹤器。
圖 3. 內核支持的跟蹤器列表

這裏要注意,如果是在 32 位 x86 機器上,編譯時不要選中 General setup 菜單項(圖 4 )下的 Optimize for size 選項(圖 5 ),否則就無法看到圖 3 中的 Kernel Function Graph Tracer 選項。這是因爲在 Kconfig 文件中,針對 32 位 x86 機器,表項 FUNCTION_GRAPH_TRACER 有一個特殊的依賴條件:
depends on !X86_32 || !CC_OPTIMIZE_FOR_SIZE
圖 4. General setup

圖 5. Optimize for size

ftrace 通過 debugfs 向用戶態提供了訪問接口,所以還需要將 debugfs 編譯進內核。激活對 debugfs 的支持,可以直接編輯內核配置文件 .config ,設置 CONFIG_DEBUG_FS=y ;或者在 make menuconfig 時到 Kernel hacking 菜單下選中對 debugfs 文件系統的支持,如圖 6 所示。
圖 6. debugfs 編譯選項

配置完成後,編譯安裝新內核,然後啓動到新內核。 注意,激活 ftrace 支持後,編譯內核時會使用編譯器的 -pg 選項,這是在 kernel/trace/Makefile 文件中定義的,如清單 2 所示。
清單 2. 激活編譯選項 -pg
ifdef CONFIG_FUNCTION_TRACER 
ORIG_CFLAGS := $(KBUILD_CFLAGS) 
KBUILD_CFLAGS = $(subst -pg,,$(ORIG_CFLAGS)) 
... 
endif 
...
使用 -pg 選項會在編譯得到的內核映像中加入大量的調試信息。一般情況下,只是在開發測試階段激活 ftrace 支持,以調試內核,修復 bug 。最終用於發行版的內核則會關閉 -pg 選項,也就無法使用 ftrace。

通過 debugfs 訪問 ftrace

ftrace 通過 debugfs 向用戶態提供訪問接口。配置內核時激活 debugfs 後會創建目錄 /sys/kernel/debug ,debugfs 文件系統就是掛載到該目錄。要掛載該目錄,需要將如下內容添加到 /etc/fstab 文件:
debugfs /sys/kernel/debug debugfs defaults 0 0
或者可以在運行時掛載:
mount -t debugfs nodev /sys/kernel/debug
激活內核對 ftrace 的支持後會在 debugfs 下創建一個 tracing 目錄 /sys/kernel/debug/tracing 。該目錄下包含了 ftrace 的控制和輸出文件,如圖 7 所示。根據編譯內核時針對 ftrace 的設定不同,該目錄下實際顯示的文件和目錄與這裏也會不同。
圖 7. tracing 目錄下的文件

ftrace 的數據文件

/sys/kernel/debug/trace 目錄下文件和目錄比較多,有些是各種跟蹤器共享使用的,有些是特定於某個跟蹤器使用的。在操作這些數據文件時,通常使用 echo 命令來修改其值,也可以在程序中通過文件讀寫相關的函數來操作這些文件的值。下面只對部分文件進行描述,讀者可以參考內核源碼包中 Documentation/trace 目錄下的文檔以及 kernel/trace 下的源文件以瞭解其餘文件的用途。
  • README文件提供了一個簡短的使用說明,展示了 ftrace 的操作命令序列。可以通過 cat 命令查看該文件以瞭解概要的操作流程。
  • current_tracer用於設置或顯示當前使用的跟蹤器;使用 echo 將跟蹤器名字寫入該文件可以切換到不同的跟蹤器。系統啓動後,其缺省值爲 nop ,即不做任何跟蹤操作。在執行完一段跟蹤任務後,可以通過向該文件寫入 nop 來重置跟蹤器。
  • available_tracers記錄了當前編譯進內核的跟蹤器的列表,可以通過 cat 查看其內容;其包含的跟蹤器與圖 3 中所激活的選項是對應的。寫 current_tracer 文件時用到的跟蹤器名字必須在該文件列出的跟蹤器名字列表中。
  • trace文件提供了查看獲取到的跟蹤信息的接口。可以通過 cat 等命令查看該文件以查看跟蹤到的內核活動記錄,也可以將其內容保存爲記錄文件以備後續查看。
  • tracing_enabled用於控制 current_tracer 中的跟蹤器是否可以跟蹤內核函數的調用情況。寫入 0 會關閉跟蹤活動,寫入 1 則激活跟蹤功能;其缺省值爲 1 。
  • set_graph_function設置要清晰顯示調用關係的函數,顯示的信息結構類似於 C 語言代碼,這樣在分析內核運作流程時會更加直觀一些。在使用 function_graph 跟蹤器時使用;缺省爲對所有函數都生成調用關係序列,可以通過寫該文件來指定需要特別關注的函數。
  • buffer_size_kb用於設置單個 CPU 所使用的跟蹤緩存的大小。跟蹤器會將跟蹤到的信息寫入緩存,每個 CPU 的跟蹤緩存是一樣大的。跟蹤緩存實現爲環形緩衝區的形式,如果跟蹤到的信息太多,則舊的信息會被新的跟蹤信息覆蓋掉。注意,要更改該文件的值需要先將 current_tracer 設置爲 nop 纔可以。
  • tracing_on用於控制跟蹤的暫停。有時候在觀察到某些事件時想暫時關閉跟蹤,可以將 0 寫入該文件以停止跟蹤,這樣跟蹤緩衝區中比較新的部分是與所關注的事件相關的;寫入 1 可以繼續跟蹤。
  • available_filter_functions記錄了當前可以跟蹤的內核函數。對於不在該文件中列出的函數,無法跟蹤其活動。
  • set_ftrace_filter和 set_ftrace_notrace在編譯內核時配置了動態 ftrace (選中 CONFIG_DYNAMIC_FTRACE 選項)後使用。前者用於顯示指定要跟蹤的函數,後者則作用相反,用於指定不跟蹤的函數。如果一個函數名同時出現在這兩個文件中,則這個函數的執行狀況不會被跟蹤。這些文件還支持簡單形式的含有通配符的表達式,這樣可以用一個表達式一次指定多個目標函數;具體使用在後續文章中會有描述。注意,要寫入這兩個文件的函數名必須可以在文件 available_filter_functions 中看到。缺省爲可以跟蹤所有內核函數,文件 set_ftrace_notrace 的值則爲空。

ftrace 跟蹤器

ftrace 當前包含多個跟蹤器,用於跟蹤不同類型的信息,比如進程調度、中斷關閉等。可以查看文件 available_tracers 獲取內核當前支持的跟蹤器列表。在編譯內核時,也可以看到內核支持的跟蹤器對應的選項,如之前圖 3 所示。
  • nop跟蹤器不會跟蹤任何內核活動,將 nop 寫入 current_tracer 文件可以刪除之前所使用的跟蹤器,並清空之前收集到的跟蹤信息,即刷新 trace 文件。
  • function跟蹤器可以跟蹤內核函數的執行情況;可以通過文件 set_ftrace_filter 顯示指定要跟蹤的函數。
  • function_graph跟蹤器可以顯示類似 C 源碼的函數調用關係圖,這樣查看起來比較直觀一些;可以通過文件 set_grapch_function 顯示指定要生成調用流程圖的函數。
  • sched_switch跟蹤器可以對內核中的進程調度活動進行跟蹤。
  • irqsoff跟蹤器和 preemptoff跟蹤器分別跟蹤關閉中斷的代碼和禁止進程搶佔的代碼,並記錄關閉的最大時長,preemptirqsoff跟蹤器則可以看做它們的組合。
ftrace 還支持其它一些跟蹤器,比如 initcall、ksym_tracer、mmiotrace、sysprof 等。ftrace 框架支持擴展添加新的跟蹤器。讀者可以參考內核源碼包中 Documentation/trace 目錄下的文檔以及 kernel/trace 下的源文件,以瞭解其它跟蹤器的用途和如何添加新的跟蹤

小結

本系列文章對 ftrace 的配置和使用進行了介紹。本文是其中的第一部分,介紹了 ftrace 的編譯配置、用戶態訪問 ftrace 的接口和 ftrace 的數據文件,並對 ftrace 所提供的部分跟蹤器的用途進行了描述。由於篇幅的限制,本文沒有對 ftrace 的具體使用和如何在代碼中與 ftrace 進行交互進行描述,這些內容將分別在本系列文章的後續篇章中給出。

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