Linux內(nèi)核學(xué)習(xí)與問題定位,這個(gè)工具一定要掌握
在Linux操作系統(tǒng)上有一個(gè)非常有用的工具,無論是進(jìn)行深層次的問題定位,還是進(jìn)行Linux內(nèi)核代碼的學(xué)習(xí),使用該工具都能達(dá)到事半功倍的效果。今天我們就介紹一下這個(gè)工具及其用法。
今天,我們主要介紹如下幾部分的內(nèi)容:
- 什么是ftrace
- ftrace的基本用法
- ftrace的實(shí)現(xiàn)原理概述
什么是 ftrace
我們可以將ftrace理解為Function tracer的簡稱,可以看出其基本功能是實(shí)現(xiàn)函數(shù)調(diào)用的跟蹤。其實(shí)ftrace不僅僅用于進(jìn)行函數(shù)調(diào)用的跟蹤,其它很多內(nèi)核信息都可以通過該工具進(jìn)行跟蹤。
除了上面函數(shù)調(diào)用跟蹤外,ftrace 還能幫我們分析內(nèi)核特定的事件,比如調(diào)度,中斷等;它還能幫我們?nèi)プ粉櫻舆t,比如中斷被屏蔽,搶占被禁止的時(shí)間,以及喚醒一個(gè)進(jìn)程之后多久開始執(zhí)行的時(shí)間等等。
因此可以理解,ftrace其實(shí)為我們提供了一個(gè)透視內(nèi)核的工具,這就像醫(yī)院的CT機(jī)或者核磁共振一樣,通過該工具我們可以了解內(nèi)核內(nèi)部的更多細(xì)節(jié)。下面我們羅列出該工具的主要功能,大家可以作為參考:
(1) Function tracer 和 Function graph tracer:跟蹤函數(shù)調(diào)用。
(2) Schedule switch tracer:跟蹤進(jìn)程調(diào)度情況。
(3) Preemptoff tracer:和前一個(gè) tracer 類似,preemptoff tracer 跟蹤并記錄禁止內(nèi)核搶占的函數(shù),并清晰地顯示出禁止搶占時(shí)間最長的內(nèi)核函數(shù)。
(4) Preemptirqsoff tracer:同上,跟蹤和記錄禁止中斷或者禁止搶占的內(nèi)核函數(shù),以及禁止時(shí)間最長的函數(shù)。
(5) Branch tracer:跟蹤內(nèi)核程序中的 likely/unlikely 分支預(yù)測(cè)命中率情況。 Branch tracer 能夠記錄這些分支語句有多少次預(yù)測(cè)成功。從而為優(yōu)化程序提供線索。
(6) Hardware branch tracer:利用處理器的分支跟蹤能力,實(shí)現(xiàn)硬件級(jí)別的指令跳轉(zhuǎn)記錄。在 x86 上,主要利用了 BTS 這個(gè)特性。
(7) Sysprof tracer:缺省情況下,sysprof tracer 每隔 1 msec 對(duì)內(nèi)核進(jìn)行一次采樣,記錄函數(shù)調(diào)用和堆棧信息。
(8) Kernel memory tracer:內(nèi)存 tracer 主要用來跟蹤 slab allocator 的分配情況。包括 kfree,kmem_cache_alloc 等 API 的調(diào)用情況,用戶程序可以根據(jù) tracer 收集到的信息分析內(nèi)部碎片情況,找出內(nèi)存分配最頻繁的代碼片斷,等等。
(9) Initcall tracer:記錄系統(tǒng)在 boot 階段所調(diào)用的 init call 。
(10) Mmiotrace tracer:記錄 memory map IO 的相關(guān)信息。
(11) Power tracer:記錄系統(tǒng)電源管理相關(guān)的信息。
(12) Workqueue statistical tracer:這是一個(gè) statistic tracer,統(tǒng)計(jì)系統(tǒng)中所有的 workqueue 的工作情況,比如有多少個(gè) work 被插入 workqueue,多少個(gè)已經(jīng)被執(zhí)行等。開發(fā)人員可以以此來決定具體的 workqueue 實(shí)現(xiàn),比如是使用 single threaded workqueue 還是 per cpu workqueue.
(13) Event tracer:跟蹤系統(tǒng)事件,比如 timer,系統(tǒng)調(diào)用,中斷等。
(14) Wakeup tracer:跟蹤進(jìn)程的調(diào)度延遲,即高優(yōu)先級(jí)進(jìn)程從進(jìn)入 ready 狀態(tài)到獲得 CPU 的延遲時(shí)間。該 tracer 只針對(duì)實(shí)時(shí)進(jìn)程。
(15) Irqsoff tracer:當(dāng)中斷被禁止時(shí),系統(tǒng)無法相應(yīng)外部事件,比如鍵盤和鼠標(biāo),時(shí)鐘也無法產(chǎn)生 tick 中斷。這意味著系統(tǒng)響應(yīng)延遲,irqsoff 這個(gè) tracer 能夠跟蹤并記錄內(nèi)核中哪些函數(shù)禁止了中斷,對(duì)于其中中斷禁止時(shí)間最長的,irqsoff 將在 log 文件的第一行標(biāo)示出來,從而使開發(fā)人員可以迅速定位造成響應(yīng)延遲的罪魁禍?zhǔn)住?/p>
ftrace的基本用法
ftrace的基本用法其實(shí)是比較簡單的。以Ubuntu18.04為例,我們只需要在current_tracer文件中輸入function字符串即可。具體操作步驟如下:
- cd /sys/kernel/debug/tracing
- echo function > current_tracer
當(dāng)執(zhí)行上述命令后,我們用vim命令打開該目錄下面一個(gè)名為trace的文件,此時(shí)就可以函數(shù)調(diào)用情況。
如果查看該文件,可能會(huì)發(fā)現(xiàn)有幾萬個(gè)函數(shù)調(diào)用,估計(jì)看著就頭大。其實(shí)它的功能要強(qiáng)大的多,比如我們通過function_graph實(shí)現(xiàn)調(diào)用棧的層級(jí)關(guān)系,此時(shí)可以更加方便的理清函數(shù)調(diào)用關(guān)系。同時(shí),我們還可實(shí)現(xiàn)函數(shù)名稱的過濾,比如只抓取某些,或者不抓取某些函數(shù)等等。
有些版本的操作系統(tǒng)可能不能直接使用該功能,這就需要進(jìn)行一些配置。關(guān)于這些配置,本文暫不介紹,后續(xù)專門進(jìn)行相關(guān)介紹。
ftrace的實(shí)現(xiàn)原理概述
ftrace最早用于跟蹤函數(shù)調(diào)用,后來隨著需求的增加,ftrace演變?yōu)橐粋€(gè)框架。也就是我們前面介紹的對(duì)內(nèi)核各種探測(cè)的功能。
整個(gè)ftrace的架構(gòu)如圖所示,其整體分為兩層,核心部分是內(nèi)核框架和一些捕獲信息的插件,其中函數(shù)調(diào)用就是其中一個(gè)插件;另外一部分則是用戶態(tài)的一些輔助工具集。
可以看出,在內(nèi)核中核心的是ftrace框架,具體功能組件是各種插件,也就是tracers。如果需要跟蹤具體的內(nèi)容,則該tracer需要注冊(cè)到框架當(dāng)中。tracer捕獲的信息會(huì)輸出到一個(gè)環(huán)形緩沖區(qū)中。整個(gè)框架中需要用到另外一個(gè)內(nèi)核模塊,也就是debugfs模塊。該模塊實(shí)現(xiàn)了用戶態(tài)與內(nèi)核的交互。
內(nèi)核態(tài)的代碼在kernel/trace目錄下面,該下面是ftrace框架和各個(gè)tracer的代碼。如下圖所示,可以看出tracer還是比較多的。
整個(gè)ftrace的代碼量也并不是特別多,大概有4萬多行的樣子。所以,目前ftrace確實(shí)是一個(gè)非常強(qiáng)大的內(nèi)核狀態(tài)監(jiān)測(cè)工具。