【Linux】BPF學習筆記 - 基本概念 [1]
本學習筆記來自於閱讀 Brendan Gregg的《BPF Performance Tools》
一、介紹
數據包篩選器(BPF) 是一種內核執行引擎,用於處理虛擬指令集,並且最近進行了擴展(又稱eBPF),這使BPF變成了通用執行引擎,可用於多種用途,包括創建高級性能分析工具。
這是一種在各種內核和應用程序事件上運行小型程序的方法。 如果您熟悉JavaScript,則可能會看到一些相似之處:JavaScript允許網站在瀏覽器事件(例如鼠標單擊)上運行微型程序,從而啓用各種新的基於Web的應用程序。 BPF允許內核在系統和應用程序事件(例如磁盤I/O)上運行微型程序,並啓用新的系統技術。 它使內核完全可編程,從而使用戶(包括非內核開發人員)能夠自定義和控制他們的系統,以解決實際問題。
根據這本書介紹BPF設計了以下工具檢查對應組件:
二、術語
1. Tracing
Tracing
是基於事件的記錄, 這些事件可以是靜態或動態,基於儀器(instrumentation)或計時器(timer)的。跟蹤器的標誌是其記錄原始事件和事件元數據的能力. 目前存在一些跟蹤器, 如:
-
Linux strace: 記錄並打印系統調用事件
-
Linux top: 不跟蹤事件,而是使用固定的統計計數器來測量事件,然後打印摘要
這樣的數據可能非常龐大,可能需要進行後續處理成摘要. BPF可以在事件上運行小型程序,以進行自定義的實時統計摘要或其他操作,從而避免進行昂貴的後續處理。
2. Sampling
Sampling
是指採取部分測量來繪製目標粗略圖片的工具, 這也稱爲Profiling
。
有一個稱爲profile
的BPF工具,它可以獲取基於計時器的運行代碼樣本。 例如,它可以每十毫秒採樣一次,或者換句話說,它每秒可以採樣一百個樣本(在每個CPU上)。 採樣器的一個優點是它們的性能開銷可以低於跟蹤器的性能開銷,因爲它們僅測量大得多的一組事件中的一個。 缺點是採樣僅能提供粗略的圖像,並且會漏掉事件。
3. Instrumentation[插樁]
一般指的是獲取計算機軟件或者硬件狀態的數據的技術, 常用實現的方法是將一段代碼注入到目標程序中,從注入目標程序的時間點的角度可分爲兩種類型:靜態插樁、動態插樁. 常用於程序監控與跟蹤. (摘自百度百科).
Dynamic instrumentation
: 也稱爲 Dynamic tracing
, 這是將檢測點插入實時軟件的能力。 BPF工具經常使用它來檢測內核和應用程序功能的開始和結束. 動態插樁存在一個問題: 當軟件版本更新時, 它的instruments方法可以被被刪除或重命名, 這稱爲接口穩定性. 但是升級內核或應用程序軟件後,可能突然發現BPF不再正常工作, 也許他會打印出無法找到 instrument 功能的錯誤,或者根本沒有任何輸出.
Static instrumentation
: 解決動態插樁的一個方案是切換到靜態工具,其中將穩定的事件名稱編碼到軟件中,並由開發人員維護。BPF跟蹤支持用於內核靜態檢測的跟蹤點和USDT
(用戶靜態定義的跟蹤, 也稱爲用戶標記. 用於用戶級靜態檢測). 靜態檢測的缺點是這些檢測點成爲開發人員的維護負擔,因此,如果存在的話,通常數量會受到限制。
三、傳統性能分析工具
下表總結了用於檢查對應組件的傳統工具,以及BPF跟蹤是否可以觀察到這些組件, 例如內核CPU調度程序,虛擬內存,文件系統等
四、BPF跟蹤工具
以下介紹主要兩種BPF的提供高級語言的前端. BCC
與bpftrace
是互補關係, bpftrace是強大的單行代碼和自定義短腳本的理想選擇,而BCC更適合使用其他庫的複雜腳本和守護程序。開發中還有另一個BPF前端,稱爲ply
,其設計輕巧且需要的依賴性極小,這使其非常適合嵌入式Linux環境。
1. bpftrace
bpftrace
是一個較新的前端,它爲開發BPF工具提供了專用的高級語言。 bpftrace代碼非常簡潔, 其建立在libbcc和libbpf庫上。
示例1:OPEN()
, 注意, bpftrace在系統範圍內進行跟蹤,因此將看到使用open的任何應用程序
# 事件: 設置一個跟蹤點 syscalls:sys_enter_open
bpftrace -e 'tracepoint:syscalls:sys_enter_open { printf("%s %s\n", comm, str(args->filename)); }'
Attaching 1 probe...
# 輸出顯示了 進程名稱 + 傳遞給open調用的文件名
slack /run/user/1000/gdm/Xauthority
slack /run/user/1000/gdm/Xauthority
slack /run/user/1000/gdm/Xauthority
slack /run/user/1000/gdm/Xauthority
^C”
但是該結果比預期的要少, 猜測缺少一些open(2) syscall
事件, 內核支持open的幾種變體,而上述只追蹤了其中一種
# 事件: 通過使用 -l 和通配符來使用bpftrace列出所有打開的跟蹤點
bpftrace -l 'tracepoint:syscalls:sys_enter_open*'
tracepoint:syscalls:sys_enter_open_by_handle_at
tracepoint:syscalls:sys_enter_open
tracepoint:syscalls:sys_enter_openat”
以下顯示的是這些跟蹤點的計數,可以看出 BPF程序在內核中有效地計算了該摘要.
bpftrace -e 'tracepoint:syscalls:sys_enter_open* { @[probe] = count(); }'
Attaching 3 probes...
^C
# 這確認了 openat 系統調用被更頻繁地調用,在跟蹤時被調用308次,而 open 系統調用僅被調用了5次
@[tracepoint:syscalls:sys_enter_open]: 5
@[tracepoint:syscalls:sys_enter_openat]: 308”
將該代碼保存到可執行文件中, opensnoop
, 可用於對故障軟件進行故障排除,例如該軟件正嘗試從錯誤的路徑打開文件,以及根據訪問權限確定配置文件和日誌文件的存放位置。它還可以識別一些性能問題,其中文件打開過快或錯誤位置檢查得過於頻繁。
# 保存爲腳本文件
opensnoop.bt
Attaching 3 probes...
Tracing open syscalls... Hit Ctrl-C to end.
PID COMM FD ERR PATH
2440 snmp-pass 4 0 /proc/cpuinfo
2440 snmp-pass 4 0 /proc/stat
25706 ls 3 0 /etc/ld.so.cache”
總結: BPF程序是在單引號內定義的,一旦按Enter鍵運行bpftrace命令,它就會編譯並運行。bpftrace還激活了open跟蹤點。 當按Control-C停止命令時,open跟蹤點被停用,並且刪除了該小型BPF程序。
BPF跟蹤工具的按需檢測就是這樣工作的:它們僅在命令的生命週期內激活並運行,生命週期可以短至幾秒鐘。
2. BCC
BCC
(BPF編譯器集合)是爲BPF開發的第一個高級跟蹤框架。 它提供了一個C編程環境,用於編寫內核BPF代碼。同時可以用其他語言(Python,lua和C ++) 編寫用戶級界面。它也是libbcc
和當前libbpf
庫的起源,它們提供了使用BPF程序檢測事件的功能。 BCC存儲庫還包含70多個BPF工具,用於性能分析和故障排除。 您可以在系統上安裝BCC,然後運行提供的工具,而無需自己編寫任何BCC代碼。
示例1: 基於BCC的execsnoop
工具, 專門用於爲追蹤短時進程而設計
execsnoop -t
# 輸出結果: 在跟蹤時執行了的進程的基本信息,包括進程 PID、父進程 PID、命令行參數等
TIME(s) PCOMM PID PPID RET ARGS
0.437 run 15524 4469 0 ./run
0.438 bash 15524 4469 0 /bin/bash
0.440 svstat 15526 15525 0 /command/svstat /service/httpd”
示例2: 基於BCC的biolatency
工具, 該輸出對高延遲非常敏感,因爲它具有服務級別協議,可以在一定毫秒內交付請求。在運行biolatency工具時,將對塊I/O事件進行檢測,並由BPF計算和彙總其延遲。當工具停止運行(Ctrl-C)時,將打印摘要. 如下圖所示, 在512到1023毫秒範圍內,有11個I/O。這些速度非常慢,被稱爲延遲異常值
biolatency -m
Tracing block device I/O... Hit Ctrl-C to end.
^C
# 打印了各個時間段的 I/O數
msecs : count distribution
0 -> 1 : 16335 |****************************************|
2 -> 3 : 2272 |***** |
8 -> 15 : 4328 |********** |
16 -> 31 : 3379 |******** |
...
512 -> 1023 : 11 | |
示例3: 在bpftrace中提到過opensnoop
, 其BCC版本可支持多種操作模式 - 可以使用不同的命令行選項來調用
# opensnoop -h
usage: opensnoop [-h] [-T] [-x] [-p PID] [-t TID] [-d DURATION] [-n NAME]
[-e] [-f FLAG_FILTER]
Trace open() syscalls
optional arguments:
-h, --help show this help message and exit
-T, --timestamp include timestamp on output
-x, --failed only show failed opens
-p PID, --pid PID trace this PID only
-t TID, --tid TID trace this TID only”
...
總結: BCC工具通常支持幾種這樣的選項來更改其行爲,從而使其比bpftrace工具更具通用性
參考文章
主要書籍: BPF Performance Tools
GCC 地址: https://github.com/iovisor/bcc
bpftrace 地址: https://github.com/iovisor/bpftrace