簡介: Trace 對於軟件的維護和性能分析相當重要,ftrace 是當前 Linux 內核中一種新的 trace 工具。本文介紹 ftrace 的使用和實現原理,並將 ftrace 和 systemTap,LTTng 等軟件進行對比,但願讀者可以對 ftrace 有一個全面的瞭解。 html
發佈日期: 2009 年 10 月 15 日
級別: 初級
訪問狀況 : 11836 次瀏覽
評論: 0 (查看 | 添加評論 - 登陸) node
平均分 (14個評分) linux
爲本文評分 數據庫
ftrace 的做用是幫助開發人員瞭解 Linux 內核的運行時行爲,以便進行故障調試或性能分析。 編程
最先 ftrace 是一個 function tracer,僅可以記錄內核的函數調用流程。現在 ftrace 已經成爲一個 framework,採用 plugin 的方式支持開發人員添加更多種類的 trace 功能。 bash
Ftrace 由 RedHat 的 Steve Rostedt 負責維護。到 2.6.30 爲止,已經支持的 tracer 包括: app
Function tracer 和 Function graph tracer: 跟蹤函數調用。 jsp
Schedule switch tracer: 跟蹤進程調度狀況。 ide
Wakeup tracer:跟蹤進程的調度延遲,即高優先級進程從進入 ready 狀態到得到 CPU 的延遲時間。該 tracer 只針對實時進程。 函數
Irqsoff tracer:當中斷被禁止時,系統沒法相應外部事件,好比鍵盤和鼠標,時鐘也沒法產生 tick 中斷。這意味着系統響應延遲,irqsoff 這個 tracer 可以跟蹤並記錄內核中哪些函數禁止了中斷,對於其中中斷禁止時間最長的,irqsoff 將在 log 文件的第一行標示出來,從而使開發人員能夠迅速定位形成響應延遲的罪魁禍首。
Preemptoff tracer:和前一個 tracer 相似,preemptoff tracer 跟蹤並記錄禁止內核搶佔的函數,並清晰地顯示出禁止搶佔時間最長的內核函數。
Preemptirqsoff tracer: 同上,跟蹤和記錄禁止中斷或者禁止搶佔的內核函數,以及禁止時間最長的函數。
Branch tracer: 跟蹤內核程序中的 likely/unlikely 分支預測命中率狀況。 Branch tracer 可以記錄這些分支語句有多少次預測成功。從而爲優化程序提供線索。
Hardware branch tracer:利用處理器的分支跟蹤能力,實現硬件級別的指令跳轉記錄。在 x86 上,主要利用了 BTS 這個特性。
Initcall tracer:記錄系統在 boot 階段所調用的 init call 。
Mmiotrace tracer:記錄 memory map IO 的相關信息。
Power tracer:記錄系統電源管理相關的信息。
Sysprof tracer:缺省狀況下,sysprof tracer 每隔 1 msec 對內核進行一次採樣,記錄函數調用和堆棧信息。
Kernel memory tracer: 內存 tracer 主要用來跟蹤 slab allocator 的分配狀況。包括 kfree,kmem_cache_alloc 等 API 的調用狀況,用戶程序能夠根據 tracer 收集到的信息分析內部碎片狀況,找出內存分配最頻繁的代碼片段,等等。
Workqueue statistical tracer:這是一個 statistic tracer,統計系統中全部的 workqueue 的工做狀況,好比有多少個 work 被插入 workqueue,多少個已經被執行等。開發人員能夠以此來決定具體的 workqueue 實現,好比是使用 single threaded workqueue 仍是 per cpu workqueue.
Event tracer: 跟蹤系統事件,好比 timer,系統調用,中斷等。
這裏尚未列出全部的 tracer,ftrace 是目前很是活躍的開發領域,新的 tracer 將不斷被加入內核。
Ftrace 最初是在 2.6.27 中出現的,那個時候,systemTap 已經開始嶄露頭角,其餘的 trace 工具包括 LTTng 等也已經發展多年。那爲何人們還要再開發一個 trace 工具呢?
SystemTap 項目是 Linux 社區對 SUN Dtrace 的反應,目標是達到甚至超越 Dtrace 。所以 SystemTap 設計比較複雜,Dtrace 做爲 SUN 公司的一個項目開發了多年才最終穩定發佈,何況獲得了 Solaris 內核中每一個子系統開發人員的大力支持。 SystemTap 想要趕超 Dtrace,困難不只是同樣,並且更大,所以她始終處在不斷完善自身的狀態下,在真正的產品環境,人們依然沒法放心的使用她。不當的使用和 SystemTap 自身的不完善都有可能致使系統崩潰。
Ftrace 的設計目標簡單,本質上是一種靜態代碼插裝技術,不須要支持某種編程接口讓用戶自定義 trace 行爲。靜態代碼插裝技術更加可靠,不會由於用戶的不當使用而致使內核崩潰。 ftrace 代碼量很小,穩定可靠。實際上,即便是 Dtrace,大多數用戶也只使用其靜態 trace 功能。所以 ftrace 的設計很是務實。
從 2.6.30 開始,ftrace 支持 event tracer,其實現和功能與 LTTng 很是相似,或許未來 ftrace 會同 LTTng 進一步融合,各自取長補短。 ftrace 有定義良好的 ASCII 接口,能夠直接閱讀,這對於內核開發人員很是具備吸引力,由於只需內核代碼加上 cat 命令就能夠工做了,至關方便; LTTng 則採用 binary 接口,更利於專門工具分析使用。此外他們內部 ring buffer 的實現不相同,ftrace 對全部 tracer 都採用同一個 ring buffer,而 LTTng 則使用各自不一樣的 ring buffer 。
目前,或許未來 LTTng 都只能是內核主分支以外的工具。她主要受到嵌入式工程師的歡迎,而內核開發人員則更喜歡 ftrace 。
Ftrace 的實現依賴於其餘不少內核特性,好比 tracepoint[3],debugfs[2],kprobe[4],IRQ-Flags[5] 等。限於篇幅,關於這些技術的介紹請讀者自行查閱相關的參考資料。
ftrace 在內核態工做,用戶經過 debugfs 接口來控制和使用 ftrace 。從 2.6.30 開始,ftrace 支持兩大類 tracer:傳統 tracer 和 Non-Tracer Tracer 。下面將分別介紹他們的使用。
使用傳統的 ftrace 須要以下幾個步驟:
用戶經過讀寫 debugfs 文件系統中的控制文件完成上述步驟。使用 debugfs,首先要掛載她。命令以下:
# mkdir /debug # mount -t debugfs nodev /debug |
此時您將在 /debug 目錄下看到 tracing 目錄。 Ftrace 的控制接口就是該目錄下的文件。
選擇 tracer 的控制文件叫做 current_tracer 。選擇 tracer 就是將 tracer 的名字寫入這個文件,好比,用戶打算使用 function tracer,可輸入以下命令:
#echo ftrace > /debug/tracing/current_tracer |
文件 tracing_enabled 控制 ftrace 的開始和結束。
#echo 1 >/debug/tracing/tracing_enable |
上面的命令使能 ftrace 。一樣,將 0 寫入 tracing_enable 文件即可以中止 ftrace 。
ftrace 的輸出信息主要保存在 3 個文件中。
下面詳細解析各類 tracer 的輸出信息。
Function tracer 的輸出
Function tracer 跟蹤函數調用流程,其 trace 文件格式以下:
# tracer: function # # TASK-PID CPU# TIMESTAMP FUNCTION # | | | | | bash-4251 [01] 10152.583854: path_put <-path_walk bash-4251 [01] 10152.583855: dput <-path_put bash-4251 [01] 10152.583855: _atomic_dec_and_lock <-dput |
能夠看到,tracer 文件相似一張報表,前 4 行是表頭。第一行顯示當前 tracer 的類型。第三行是 header 。
對於 function tracer,該表將顯示 4 列信息。首先是進程信息,包括進程名和 PID ;第二列是 CPU,在 SMP 體系下,該列顯示內核函數具體在哪個 CPU 上執行;第三列是時間戳;第四列是函數信息,缺省狀況下,這裏將顯示內核函數名以及它的上一層調用函數。
經過對這張報表的解讀,用戶即可以得到完整的內核運行時流程。這對於理解內核代碼也有很大的幫助。有志於精讀內核代碼的讀者,或許能夠考慮考慮 ftrace 。
如上例所示,path_walk() 調用了 path_put 。此後 path_put 又調用了 dput,進而 dput 再調用 _atomic_dec_and_lock 。
Schedule switch tracer 的輸出
Schedule switch tracer 記錄系統中的進程切換信息。在其輸出文件 trace 中 , 輸出行的格式有兩種:
第一種表示進程切換信息:
Context switches: Previous task Next Task <pid>:<prio>:<state> ==> <pid>:<prio>:<state> |
第二種表示進程 wakeup 的信息:
Wake ups: Current task Task waking up <pid>:<prio>:<state> + <pid>:<prio>:<state> |
這裏舉一個實例:
# tracer: sched_switch # # TASK_PID CPU# TIMESTAMP FUNCTION # | | | | fon-6263 [000] 4154504638.932214: 6263:120:R + 2717:120:S fon-6263 [000] 4154504638.932214: 6263:120:? ==> 2717:120:R bash-2717 [000] 4154504638.932214: 2717:120:S + 2714:120:S |
第一行表示進程 fon 進程 wakeup 了 bash 進程。其中 fon 進程的 pid 爲 6263,優先級爲 120,進程狀態爲 Ready 。她將進程 ID 爲 2717 的 bash 進程喚醒。
第二行表示進程切換髮生,從 fon 切換到 bash 。
irqsoff tracer 輸出
有四個 tracer 記錄內核在某種狀態下最長的時延,irqsoff 記錄系統在哪裏關中斷的時間最長; preemptoff/preemptirqsoff 以及 wakeup 分別記錄禁止搶佔時間最長的函數,或者系統在哪裏調度延遲最長 (wakeup) 。這些 tracer 信息對於實時應用具備很高的參考價值。
爲了更好的表示延遲,ftrace 提供了和 trace 相似的 latency_trace 文件。以 irqsoff 爲例演示如何解讀該文件的內容。
# tracer: irqsoff irqsoff latency trace v1.1.5 on 2.6.26 -------------------------------------------------------------------- latency: 12 us, #3/3, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:2) ----------------- | task: bash-3730 (uid:0 nice:0 policy:0 rt_prio:0) ----------------- => started at: sys_setpgid => ended at: sys_setpgid # _------=> CPU# # / _-----=> irqs-off # | / _----=> need-resched # || / _---=> hardirq/softirq # ||| / _--=> preempt-depth # |||| / # ||||| delay # cmd pid ||||| time | caller # \ / ||||| \ | / bash-3730 1d... 0us : _write_lock_irq (sys_setpgid) bash-3730 1d..1 1us+: _write_unlock_irq (sys_setpgid) bash-3730 1d..2 14us : trace_hardirqs_on (sys_setpgid) |
在文件的頭部,irqsoff tracer 記錄了中斷禁止時間最長的函數。在本例中,函數 trace_hardirqs_on 將中斷禁止了 12us 。
文件中的每一行表明一次函數調用。 Cmd 表明進程名,pid 是進程 ID 。中間有 5 個字符,分別表明了 CPU#,irqs-off 等信息,具體含義以下:
CPU# 表示 CPU ID ;
irqs-off 這個字符的含義以下:’ d ’表示中斷被 disabled 。’ . ’表示中斷沒有關閉;
need-resched 字符的含義:’ N ’表示 need_resched 被設置,’ . ’表示 need-reched 沒有被設置,中斷返回不會進行進程切換;
hardirq/softirq 字符的含義 : 'H' 在 softirq 中發生了硬件中斷, 'h' – 硬件中斷,’ s ’表示 softirq,’ . ’不在中斷上下文中,普通狀態。
preempt-depth: 當搶佔中斷使能後,該域表明 preempt_disabled 的級別。
在每一行的中間,還有兩個域:time 和 delay 。 time: 表示從 trace 開始到當前的相對時間。 Delay 突出顯示那些有高延遲的地方以便引發用戶注意。當其顯示爲 ! 時,表示須要引發注意。
function graph tracer 輸出
Function graph tracer 和 function tracer 相似,但輸出爲函數調用圖,更加容易閱讀:
# tracer: function_graph # # CPU OVERHEAD/DURATION FUNCTION CALLS # | | | | | | | 0) | sys_open() { 0) | do_sys_open() { 0) | getname() { 0) | kmem_cache_alloc() { 0) 1.382 us | __might_sleep(); 0) 2.478 us | } 0) | strncpy_from_user() { 0) | might_fault() { 0) 1.389 us | __might_sleep(); 0) 2.553 us | } 0) 3.807 us | } 0) 7.876 us | } 0) | alloc_fd() { 0) 0.668 us | _spin_lock(); 0) 0.570 us | expand_files(); 0) 0.586 us | _spin_unlock(); |
OVERHEAD 爲 ! 時提醒用戶注意,該函數的性能比較差。上面的例子中能夠看到 sys_open 調用了 do_sys_open,依次又調用了 getname(),依此類推。
Sysprof tracer 的輸出
Sysprof tracer 定時對內核進行採樣,她的輸出文件中記錄了每次採樣時內核正在執行哪些內核函數,以及當時的內核堆棧狀況。
每一行前半部分的格式和 3.1.1 中介紹的 function tracer 同樣,只是,最後一部分 FUNCTION 有所不一樣。
Sysprof tracer 中,FUNCTION 列格式以下:
Identifier address frame_pointer/pid |
當 identifier 爲 0 時,表明一次採樣的開始,此時第三個數字表明當前進程的 PID ;
Identifier 爲 1 表明內核態的堆棧信息;當 identifier 爲 2 時,表明用戶態堆棧信息;顯示堆棧信息時,第三列顯示的是 frame_pointer,用戶可能須要打開 system map 文件查找具體的符號,這是 ftrace 有待改進的一個地方吧。
當 identifier 爲 3 時,表明一次採樣結束。
從 2.6.30 開始,ftrace 還支持幾種 Non-tracer tracer,所謂 Non-tracer tracer 主要包括如下幾種:
和傳統的 tracer 不一樣,Non-Tracer Tracer 並不對每一個內核函數進行跟蹤,而是一種相似邏輯分析儀的模式,即對系統進行採樣,但彷佛也不徹底如此。不管怎樣,這些 tracer 的使用方法和前面所介紹的 tracer 的使用稍有不一樣。下面我將試圖描述這些 tracer 的使用方法。
Max Stack Tracer 的使用
這個 tracer 記錄內核函數的堆棧使用狀況,用戶可使用以下命令打開該 tracer:
# echo 1 > /proc/sys/kernel/stack_tracer_enabled |
今後,ftrace 便留心記錄內核函數的堆棧使用。 Max Stack Tracer 的輸出在 stack_trace 文件中:
# cat /debug/tracing/stack_trace Depth Size Location (44 entries) ----- ---- -------- 0) 3088 64 update_curr+0x64/0x136 1) 3024 64 enqueue_task_fair+0x59/0x2a1 2) 2960 32 enqueue_task+0x60/0x6b 3) 2928 32 activate_task+0x27/0x30 4) 2896 80 try_to_wake_up+0x186/0x27f … 42) 80 80 sysenter_do_call+0x12/0x32 |
從上例中能夠看到內核堆棧最滿的狀況以下,有 43 層函數調用,堆棧使用大小爲 3088 字節。此外還能夠在 Location 這列中看到整個的 calling stack 狀況。這在某些狀況下,能夠提供額外的 debug 信息,幫助開發人員定位問題。
Branch tracer
Branch tracer 比較特殊,她有兩種模式,便是傳統 tracer,又實現了 profiling tracer 模式。
做爲傳統 tracer 。其輸出文件爲 trace,格式以下:
# tracer: branch # # TASK-PID CPU# TIMESTAMP FUNCTION # | | | | | Xorg-2491 [000] 688.561593: [ ok ] fput_light:file.h:29 Xorg-2491 [000] 688.561594: [ ok ] fput_light:file_table.c:330 |
在 FUNCTION 列中,顯示了 4 類信息:
函數名,文件和行號,用中括號引發來的部分,顯示了分支的信息,假如該字符串爲 ok,代表 likely/unlikely 返回爲真,不然字符串爲 MISS 。舉例來講,在文件 file.h 的第 29 行,函數 fput_light 中,有一個 likely 分支在運行時解析爲真。咱們看看 file.h 的第 29 行:
static inline void fput_light(struct file *file, int fput_needed) {LINE29: if (unlikely(fput_needed)) fput(file); } |
Trace 結果告訴咱們,在 688 秒的時候,第 29 行代碼被執行,且預測結果爲 ok,即 unlikely 成功。
Branch tracer 做爲 profiling tracer 時,其輸出文件爲 profile_annotated_branch,其中記錄了 likely/unlikely 語句完整的統計結果。
#cat trace_stat/branch_ annotated correct incorrect % function file line ------- ---------- ---- ------------------ -------------- ----- 0 46 100 pre_schedule_rt sched_rt.c 1449 |
下面是文件 sched_rt.c 的第 1449 行的代碼:
if (unlikely(rt_task(prev)) && rq->rt.highest_prio.curr > prev->prio) pull_rt_task(rq); |
記錄代表,unlikely 在這裏有 46 次爲假,命中率爲 100% 。假如爲真的次數更多,則說明這裏應該改爲 likely 。
Workqueue profiling
假如您在內核編譯時選中該 tracer,ftrace 便會統計 workqueue 使用狀況。您只需使用下面的命令查看結果便可:
#cat /debug/tracing/trace_stat/workqueue |
典型輸出以下:
# CPU INSERTED EXECUTED NAME # | | | | 0 38044 38044 events/0 0 426 426 khelper 0 9853 9853 kblockd/0 0 0 0 kacpid … |
能夠看到 workqueue events 在 CPU 0 上有 38044 個 worker 被插入並執行。
Event tracer
Event tracer 不間斷地記錄內核中的重要事件。用戶能夠用下面的命令查看 ftrace 支持的事件。
#cat /debug/tracing/available_event |
下面以跟蹤進程切換爲例講述 event tracer 的使用。首先打開 event tracer,並記錄進程切換:
# echo sched:sched_switch >> /debug/tracing/set_event # echo sched_switch >> /debug/tracing/set_event # echo 1 > /debug/tracing/events/sched/sched_switch/enable |
上面三個命令的做用是同樣的,您能夠任選一種。
此時能夠查看 ftrace 的輸出文件 trace:
>head trace # tracer: nop # # TASK-PID CPU# TIMESTAMP FUNCTION # | | | | | <idle>-0 [000] 12093.091053: sched_switch: task swapper:0 [140] ==> /user/bin/sealer:2612 [120] |
我想您會發現該文件很容易解讀。如上例,表示一個進程切換 event,從 idle 進程切換到 sealer 進程。
研究 tracer 的實現是很是有樂趣的。理解 ftrace 的實現可以啓發咱們在本身的系統中設計更好的 trace 功能。
Ftrace 的總體構架:
Ftrace 有兩大組成部分,一是 framework,另外就是一系列的 tracer 。每一個 tracer 完成不一樣的功能,它們統一由 framework 管理。 ftrace 的 trace 信息保存在 ring buffer 中,由 framework 負責管理。 Framework 利用 debugfs 系統在 /debugfs 下創建 tracing 目錄,並提供了一系列的控制文件。
本文並不打算系統介紹 tracer 和 ftrace framework 之間的接口,只是打算從純粹理論的角度,簡單剖析幾種具體 tracer 的實現原理。假如讀者須要開發新的 tracer,能夠參考某個 tracer 的源代碼。
Ftrace 採用 GCC 的 profile 特性在全部內核函數的開始部分加入一段 stub 代碼,ftrace 重載這段代碼來實現 trace 功能。
gcc 的 -pg 選項將在每一個函數入口處加入對 mcount 的調用代碼。好比下面的 C 代碼。
//test.c void foo(void) { printf( 「 foo 」 ); } |
用 gcc 編譯:
gcc – S test.c |
反彙編以下:
_foo: pushl %ebp movl %esp, %ebp subl $8, %esp movl $LC0, (%esp) call _printf leave ret |
再加入 -gp 選項編譯:
gcc – pg – S test.c |
獲得的彙編以下:
_foo: pushl %ebp movl %esp, %ebp subl $8, %esp LP3: movl $LP3,%edx call _mcount movl $LC0, (%esp) call _printf leave ret |
增長 pg 選項後,gcc 在函數 foo 的入口處加入了對 mcount 的調用:call _mcount 。本來 mcount 由 libc 實現,但您知道內核不會鏈接 libc 庫,所以 ftrace 編寫了本身的 mcount stub 函數,並藉此實現 trace 功能。
在每一個內核函數入口加入 trace 代碼,必然會影響內核的性能,爲了減少對內核性能的影響,ftrace 支持動態 trace 功能。
當 CONFIG_DYNAMIC_FTRACE 被選中後,內核編譯時會調用一個 perl 腳本:recordmcount.pl 將每一個函數的地址寫入一個特殊的段:__mcount_loc
在內核初始化的初期,ftrace 查詢 __mcount_loc 段,獲得每一個函數的入口地址,並將 mcount 替換爲 nop 指令。這樣在默認狀況下,ftrace 不會對內核性能產生影響。
當用戶打開 ftrace 功能時,ftrace 將這些 nop 指令動態替換爲 ftrace_caller,該函數將調用用戶註冊的 trace 函數。其具體的實如今相應 arch 的彙編代碼中,以 x86 爲例,在 entry_32.s 中:
ENTRY(ftrace_caller) cmpl $0, function_trace_stop jne ftrace_stub pushl %eax pushl %ecx pushl %edx movl 0xc(%esp), %eax movl 0x4(%ebp), %edx subl $MCOUNT_INSN_SIZE, %eax .globl ftrace_call ftrace_call: call ftrace_stubline 10popl %edx popl %ecx popl %eax .globl ftrace_stub ftrace_stub: ret END(ftrace_caller) |
Function tracer 將 line10 這行代碼替換爲 function_trace_call() 。這樣每一個內核函數都將調用 function_trace_call() 。
在 function_trace_call() 函數內,ftrace 記錄函數調用堆棧信息,並將結果寫入 ring buffer,稍後,用戶能夠經過 debugfs 的 trace 文件讀取該 ring buffer 中的內容。
Irqsoff tracer 的實現依賴於 IRQ-Flags 。 IRQ-Flags 是 Ingo Molnar 維護的一個內核特性。使得用戶可以在中斷關閉和打開時獲得通知,ftrace 重載了其通知函數,從而可以記錄中斷禁止時間。即,中斷被關閉時,記錄下當時的時間戳。此後,中斷被打開時,再計算時間差,由此即可獲得中斷禁止時間。
IRQ-Flags 封裝開關中斷的宏定義:
#define local_irq_enable() \ do { trace_hardirqs_on (); raw_local_irq_enable(); } while (0) |
ftrace 在文件 ftrace_irqsoff.c 中重載了 trace_hardirqs_on 。具體代碼再也不羅列,主要是使用了 sched_clock()函數來得到時間戳。
Hw-branch 只在 IA 處理器上實現,依賴於 x86 的 BTS 功能。 BTS 將 CPU 實際執行到的分支指令的相關信息保存下來,即每一個分支指令的源地址和目標地址。
軟件能夠指定一塊 buffer,處理器將每一個分支指令的執行狀況寫入這塊 buffer,以後,軟件即可以分析這塊 buffer 中的功能。
Linux 內核的 DS 模塊封裝了 x86 的 BTS 功能。 Debug Support 模塊封裝了和底層硬件的接口,主要支持兩種功能:Branch trace store(BTS) 和 precise-event based sampling (PEBS) 。 ftrace 主要使用了 BTS 功能。
內核代碼中常使用 likely 和 unlikely 提升編譯器生成的代碼質量。 Gcc 能夠經過合理安排彙編代碼最大限度的利用處理器的流水線。合理的預測是 likely 可以提升性能的關鍵,ftrace 爲此定義了 branch tracer,跟蹤程序中 likely 預測的正確率。
爲了實現 branch tracer,從新定義了 likely 和 unlikely 。具體的代碼在 compiler.h 中。
# ifndef likely # define likely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 1)) # endif # ifndef unlikely # define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0)) # endif |
其中 __branch_check 的實現以下:
#define __branch_check__(x, expect) ({\ int ______r; \ static struct ftrace_branch_data \ __attribute__((__aligned__(4))) \ __attribute__((section("_ftrace_annotated_branch"))) \ ______f = { \ .func = __func__, \ .file = __FILE__, \ .line = __LINE__, \ }; \ ______r = likely_notrace(x);\ ftrace_likely_update(&______f, ______r, expect); \ ______r; \ }) |
ftrace_likely_update() 將記錄 likely 判斷的正確性,並將結果保存在 ring buffer 中,以後用戶能夠經過 ftrace 的 debugfs 接口讀取分支預測的相關信息。從而調整程序代碼,優化性能。
本文講解了 ftrace 的基本使用。在實踐中,ftrace 是一個很是有效的性能調優和 debug 分析工具,每一個人使用她的方法和角度都不相同,必定有不少 best practice,這非本文所能涉及。但但願經過本文的講解,能讓讀者對 ftrace 造成一個基本的瞭解,進而在具體工做中使用她。
劉明,從事嵌入式軟件開發,熱愛開源軟件。喜歡學習和使用 linux,目前致力於數據庫方面的工做和研究