前言
極客時間 eBPF 核心技術與實戰 的學習筆記.
本章簡單介紹一下 eBPF 的發展和概述
正文
eBPF發展歷史
注意區分 BPF 和 eBPF
提案
1992年 USENUX 會議上提出BPF機制來在 linux 中進行包過濾
- 在核心態中引入虛擬機器執行 BPF 指令
- 在使用者態使用 BPF 位元組碼來進行表示式的自定義, 然後交由核心態中的虛擬機器來執行
- 因為直接在核心態進行過濾, 避免了每個包都複製到使用者態, 相比傳統方式提高了效能
加入
linux 2.1.75(1997年)版本中首次引入了 BPF 技術
linux 3.0(2011年)替換了原先的 BPF 直譯器,進一步提升了執行效率
eBPF
linux 3.18(2014年) BPF 升級為 eBPF, 將BPF虛擬機器由原來的包過濾功能擴大到支援通用功能
linux 4.x 繼續迭代 eBPF, 先後支援了 函式/跟蹤點/效能事件/安全控制 等, eBPF快速發展
eBPF 工作方式
eBPF只有在需要觸發時(事件觸發)才會執行, 比如 系統呼叫/網路事件 等等, 現如今, eBPF 幾乎可以在系統的任意部分進行插樁
執行流程
- 將 eBPF 程式轉換成 BPF 位元組碼
- BPF 系統接受到 BPF 位元組碼
- BPF 系統檢查 BPF 位元組碼是否安全和可靠(避免影響系統正常執行)
- 提交到即時編譯器執行
典型的不安全程式邏輯
- 包含無限迴圈
- 可能導致核心崩潰
- 在有限時間內不能執行完成
資料傳輸
使用者編寫的 eBPF 程式一般分為兩部分, 在使用者態執行的部分負責邏輯處理, 而在核心態執行的部分負責對資料進行抓取和簡單篩選, 而後傳輸給使用者態部分.
如何在兩個態之間進行資料的傳輸? 答案是 BPF 對映(map)
eBPF限制
常見的 eBPF 限制
- eBPF程式必須經過安全性校驗, 驗證失敗則不允許執行
- 必須是特權程序執行
- 不能隨意呼叫系統核心函式, 只能呼叫在 BPF 系統中定義的 API
- eBPF 自帶的棧空間只有512位元組, 想要更大的儲存, 只能使用 map(BPF 對映)
- linux 核心的升級, 可能會導致之前的eBPF 程式執行錯誤, 可能需要調整原始碼或者重新編譯
- eBPF 程式最好在 linux核心版本大於 4.9 以上的系統執行, 最好是 5.x 及以上(截止到2024年12月1日, linux核心的穩定版本是 6.12.1)