【Linux】BPF學習筆記 - 基本概念 [1]

【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的提供高級語言的前端. BCCbpftrace是互補關係, 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

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