- 深入理解eBPF與可觀測性
- 毛文安 鄭昱笙 程書意 廖肇燕
- 986字
- 2025-06-09 17:11:24
1.1.1 Linux的跟蹤與診斷技術簡介
在eBPF出現之前,Linux已經提供了多種跟蹤與診斷基礎功能模塊,包括kprobe/kretprobe、uprobe/uretprobe、fentry/fexit以及tracepoint。這些功能模塊為跟蹤和診斷提供了豐富的支持。目前,大部分eBPF的跟蹤與診斷功能都是基于這些功能模塊實現的。接下來,我們將分別介紹這些功能的工作原理,以便更好地理解eBPF的工作原理。
1)kprobe/kretprobe:kprobe用于在函數的入口處插入代碼進行跟蹤和調試;kretprobe是kprobe的擴展,用于在函數的返回處插入代碼進行跟蹤和調試。
kprobe/kretprobe的工作原理如圖1-1所示。首先,被探測的函數入口指令會被替換成int 3指令。當被跟蹤的函數執行時,將引發int 3異常中斷,然后int 3異常處理程序將被觸發,進而調用相應的kprobe處理函數。kprobe的處理函數有兩種:一種是執行用戶所注冊的kprobe函數;另一種是執行通過kretprobe機制注冊的kprobe函數。值得注意的是,通過kretprobe注冊的kprobe處理函數會更改函數的返回地址,將該地址替換為kprobe處理函數的地址。因此,當程序執行ret指令并返回時,將直接跳轉至kretprobe的處理函數處,并執行用戶所注冊的kretprobe函數。

圖1-1 kprobe/kretprobe工作原理
2)uprobe/uretprobe:與kprobe/kretprobe的運作機制基本相似,但uprobe/uretprobe跟蹤的是用戶態函數。uretprobe作為uprobe的補充功能,當部署uretprobe函數時,會同時部署uprobe處理函數,以便將函數的返回地址更改為uretprobe處理函數的地址。這樣,當函數執行完畢并準備返回時,將直接跳轉至uretprobe處理函數并繼續執行相應的操作。
3)fentry/fexit:相較于kprobe/kretprobe通過int 3指令來觸發執行kprobe處理程序,fentry/fexit的實現方式略有不同。在內核編譯時,它會通過GCC(GNU Compiler Collection,一個開源的編譯器系統)的編譯選項-mfentry在每個函數的入口處加入NOP指令[1]。當用戶插入具體的fentry/fexit處理函數時,這些NOP指令會被替換成調用相應的處理函數指令。盡管ftrace早期就使用了fentry/fexit功能,但直到Linux內核5.5版本,用戶才能直接使用該功能。值得一提的是,fexit的實現原理與kretprobe和uretprobe相同,也是在fentry處理函數內將函數的返回地址更改成fexit處理函數的地址。
4)tracepoint:tracepoint是在內核中定義的一系列預定義的事件跟蹤點。這些跟蹤點位于內核代碼中的關鍵位置,允許開發人員插入自定義的跟蹤代碼,以捕獲特定事件的信息。我們可以在/sys/kernel/debug/tracing/events/目錄看到內核支持的跟蹤點。它與fentry/fexit具有一樣高的性能。
盡管kprobe/kretprobe、uprobe/uretprobe、fentry/fexit和tracepoint都具有跟蹤診斷功能,但各自具有獨特的意義。kprobe和uprobe雖然性能相對較差,但具有高度的靈活性,可以在內核中的任意位置進行跟蹤。相比之下,fentry/fexit和tracepoint性能最佳,但靈活性稍差,只能跟蹤特定的內核位置。我們還從靈活性、性能和支持eBPF的內核版本等關鍵指標進行了總結和比較,如表1-1所示。
表1-1 關鍵指標對比

- 嵌入式操作系統(Linux篇)(微課版)
- Windows Vista融會貫通
- Linux系統安全基礎:二進制代碼安全性分析基礎與實踐
- 直播系統開發:基于Nginx與Nginx-rtmp-module
- 突破平面3ds Max動畫設計與制作
- 計算機應用基礎(Windows 7+Office 2016)
- iOS 8開發指南
- Cassandra 3.x High Availability(Second Edition)
- 跟老男孩學Linux運維:Shell編程實戰
- OpenVZ Essentials
- Linux從入門到精通(視頻教學版)
- Windows 8完全自學手冊
- 辦公自動化教程(Windows7+Office2010)
- Linux深度攻略
- Mastering Azure Serverless Computing