eBPF-學習指北

背景

從3.18版本開始,Linux 內核提供了一種擴展的BPF虛擬機,被稱爲“extended BPF“,簡稱爲eBPF。它能夠被用於非網絡相關的功能,比如附在不同的tracepoints上,從而獲取當前內核運行的許多信息。

傳統的BPF,現在被稱爲“classical BPF”。主要用於過濾網絡包,Android中的DHCP數據包,就使用BPF來進行過濾。

eBPF由Alexei Starovoitov在PluMgrid工作時設計,這家公司專注於研究新的方法來設計軟件定義網絡解決方案。在它只是一個提議時,Daniel Borkmann——Red Hat公司的內核工程師,幫助修改使得它能夠進入內核代碼並完全替代已有的BPF實現。這是二十年來BPF首次主要的更新,使得BPF成爲了一個通用的虛擬機。

因爲eBPF虛擬機使用的是類似於彙編語言的指令,對於程序編寫來說直接使用難度非常大。和將C語言生成彙編語言類似,現在的編譯器正在逐步完善從更高級的語言生成BPF虛擬機使用的指令。LLVM在3.7版本開始支持BPF作爲後端輸出。GCC 10也將會支持BPF作爲後端。BCC是IOVisor項目下的編譯器工具集,用於創建內核跟蹤(tracing)工具。bpftrace是爲eBPF設計的高級跟蹤語言,在Linux內核(4.x)中提供。

學習新知識的時候,先有一個宏觀的認識,再去深究其中的細節。

什麼是eBPF?

在講eBPF之前,先簡要說下BPF(Berkeley Packet Filter,縮寫 BPF),其是類Unix系統上數據鏈路層的一種原始接口,提供原始鏈路層封包的收發。除此之外,如果網卡驅動支持混雜模式,那麼它可以讓網卡處於此種模式,這樣可以收到網絡上的所有包,不管他們的目的地是不是所在主機。
另外,BPF支持過濾數據包——用戶態的進程可以提供一個過濾程序來聲明它想收到哪些數據包。通過這種過濾可以避免從操作系統內核向用戶態複製其他對用戶態程序無用的數據包,從而極大地提高性能。

eBPF是一種內核注入技術,開發者可以使用高級語言(GO、Python、C等)來編寫eBPF代碼,然後注入到kernel中運行。

首先,我們需要編寫代碼,爲了編碼的方便,就出現了像BCCbpftrace這樣的框架來方便我們coding。

編寫完代碼後,我們需要編譯,目前可以使用clang、llvm(GCC正在開發中),生成的elf文件,使用kernel提供的load接口loading到內核態。
可以使用readelf來查看編譯的.o

其次,loading到kernel的程序,必須通過verify,這是必要且必須的操作,內核態的東西不是想怎麼執行都可以的。verifier.c 如果想詳細瞭解檢查機制,沒有別閱讀源碼更有效的了

最後,“程序=數據結構+算法”,這是不變的真理;
eBPF的數據結構就是MAP,它新開闢了一個VFS(BPF_FS),用來用戶態和內核態進行交互,你可以在/sys/fs/bpf下面找到定義的MAP和PROG。
eBPF的算法,可以有kprobe、tracepoint、perf、netfilter等等,這些都是原有的內核跟蹤技術,eBPF就像ftrace一樣,再一次把它們聚在了一起。

一句話,eBPF既是一種內核注入技術,又是一種內核跟蹤技術,也是一種調試框架。你可以在學習理論的同時,使用它來跟蹤Linux的行爲,更爲形象和直觀的瞭解操作系統。

使用eBPF能做什麼?

eBPF現在被應用於網絡、跟蹤、內核優化、硬件建模等領域。

如何學習eBPF?

  • 誠然,現在網上已經很多關於eBPF的文章和資料了,但我還是推薦以下兩本書。

入門:Linux Observability with BPF Advanced Programming for Performance Analysis and Networking
進階:BPF Performance Tools

參考資料

閱讀代碼的同時,參考這兩個也足夠了。
內核官方文檔,沒有比這更正宗的了,直接reading it
Brendan Gregg Blog

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