<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一文看懂eBPF|eBPF的簡單使用

          共 3741字,需瀏覽 8分鐘

           ·

          2022-03-16 00:22

          eBPF(extended Berkeley Packet Filter)?可謂 Linux 社區(qū)的新寵,很多大公司都開始投身于?eBPF?技術(shù),如 Goole、Facebook、Twitter 等。

          eBPF 究竟有什么魅力讓大家都關(guān)注它呢?

          這是因為 eBPF 增加了內(nèi)核的可擴展性,讓內(nèi)核變得更加靈活和強大。

          如果大家玩過?樂高積木?的話就會深有體會,樂高積木就是通過不斷向主體添加積木來組合出更龐大的模型。

          而 eBPF 就像樂高積木一樣,可以不斷向內(nèi)核添加 eBPF 模塊來增強內(nèi)核的功能。

          本文分為3篇:

          1. eBPF 的簡單使用
          2. eBPF 的實現(xiàn)原理
          3. kprobes 在 eBPF 中的實現(xiàn)原理

          看完這3篇文章,估計對 eBPF 也有較深的理解了。

          什么是 eBPF

          eBPF 全稱 extended Berkeley Packet Filter,中文意思是?擴展的伯克利包過濾器。一般來說,要向內(nèi)核添加新功能,需要修改內(nèi)核源代碼或者編寫?內(nèi)核模塊?來實現(xiàn)。而 eBPF 允許程序在不修改內(nèi)核源代碼,或添加額外的內(nèi)核模塊情況下運行。

          從 eBPF 的名字看,好像是專門為過濾網(wǎng)絡(luò)包而創(chuàng)造的。其實,eBPF 是從 BPF(也稱為 cBPF:classic Berkeley Packet Filter)發(fā)展而來的,BPF 是專門為過濾網(wǎng)絡(luò)數(shù)據(jù)包而創(chuàng)造的。

          但隨著 eBPF 不斷完善和加強,現(xiàn)在的 eBPF 已經(jīng)不再限于過濾網(wǎng)絡(luò)數(shù)據(jù)包了。

          eBPF 架構(gòu)

          我們先來看看 eBPF 的架構(gòu),如下圖所示:


          下面用文字來描述一下:

          用戶態(tài)

          1. 用戶編寫 eBPF 程序,可以使用 eBPF 匯編或者 eBPF 特有的 C 語言來編寫。
          2. 使用 LLVM/CLang 編譯器,將 eBPF 程序編譯成 eBPF 字節(jié)碼。
          3. 調(diào)用?bpf()?系統(tǒng)調(diào)用把 eBPF 字節(jié)碼加到內(nèi)核。

          內(nèi)核態(tài)

          1. 當(dāng)用戶調(diào)用?bpf()?系統(tǒng)調(diào)用把 eBPF 字節(jié)碼加載到內(nèi)核時,內(nèi)核先會對 eBPF 字節(jié)碼進(jìn)行安全驗證。
          2. 使用?JIT(Just In Time)技術(shù)將 eBPF 字節(jié)編譯成本地機器碼(Native Code)。
          3. 然后根據(jù) eBPF 程序的功能,將 eBPF 機器碼掛載到內(nèi)核的不同運行路徑上(如用于跟蹤內(nèi)核運行狀態(tài)的 eBPF 程序?qū)燧d在?kprobes?的運行路徑上)。當(dāng)內(nèi)核運行到這些路徑時,就會觸發(fā)執(zhí)行相應(yīng)路徑上的 eBPF 機器碼。

          如果大家使用過 Java 編寫程序的話,會發(fā)現(xiàn) eBPF 與 Java 的AOP(Aspect Oriented Programming 面向切面編程)概念很像。

          為了讓有 Java 經(jīng)驗的同學(xué)更容易接受 eBPF 技術(shù)。我們先介紹一下 Java 中的 AOP 概念。

          在 AOP 概念中,有兩個很重要的角色:切點?和?攔截器

          1. 切點:程序中某個具體的業(yè)務(wù)點(方法)。
          2. 攔截器:攔截器其實是一段 Java 代碼,用于攔截切點在執(zhí)行前(或執(zhí)行后),先運行這段 Java 代碼。

          eBPF 程序就像 AOP 中的攔截器,而內(nèi)核的某個運行路徑就像 AOP 中的切點。

          根據(jù)掛載點功能的不同,大概可以分為以下幾個模塊:

          1. 性能跟蹤
          2. 網(wǎng)絡(luò)
          3. 容器
          4. 安全

          eBPF 使用

          在介紹 eBPF 的實現(xiàn)前,我們先來介紹一下如何使用 eBPF 來跟蹤?fork()?系統(tǒng)調(diào)用的運行情況。

          編寫 eBPF 程序有多種方式,比如使用原生 eBPF 匯編來編寫,但使用原生 eBPF 匯編編寫程序的難度較大,所以一般不建議。

          也可以使用 eBPF 受限的 C 語言來編寫,難度比使用原生 eBPF 匯編簡單些,但對初學(xué)者來說也不是十分友好。

          最簡單是使用 BCC 工具來編寫,BCC 工具幫我們簡化了很多繁瑣的工作,比如不用編寫加載器。

          下面我們將使用 BCC 工具來介紹怎么編寫一個 eBPF 程序。

          注意:由于 eBPF 對內(nèi)核的版本有較高的要求,不同版本的內(nèi)核對 eBPF 的支持可能有所不相同。所以使用 eBPF 時,最好使用最新版本的內(nèi)核。

          本文使用?Ubuntu 20.20(內(nèi)核版本為5.8.1)作為解說。

          1. BCC 工具安裝

          在 Ubuntu 系統(tǒng)中安裝 BCC 工具是比較簡單的,可以使用以下命令:

          $?sudo?apt-get?install?bpfcc-tools?linux-headers-$(uname?-r)

          BCC 工具可以讓你使用 Python 和 C 語言組合來編寫 eBPF 程序。

          安裝完成后,可以使用命令?bcc -v?來測試是否安裝成功。如果安裝失敗,可以參考官網(wǎng)安裝文檔,如下:

          https://github.com/iovisor/bcc/blob/master/INSTALL.md

          2. 編寫 eBPF 版的 hello world

          一般編程課的第一步都是編寫著名的?hello world?程序,所以我們也以編寫?hello world?程序作為第一步吧。

          使用 BCC 編寫 eBPF 程序的步驟如下:

          1. 使用 C 語言編寫 eBPF 程序的內(nèi)核態(tài)功能(也就是運行在內(nèi)核態(tài)的 eBPF 程序)。
          2. 使用 Python 編寫加載代碼和用戶態(tài)功能。

          為什么不能全部使用 Python 編寫呢?這是因為 LLVM/Clang 只支持將 C 語言編譯成 eBPF 字節(jié)碼,而不支持將 Python 代碼編譯成 eBPF 字節(jié)碼。

          所以,eBPF 內(nèi)核態(tài)程序只能使用 C 語言編寫。而 eBPF 的用戶態(tài)程序可以使用 Python 進(jìn)行編寫,這樣就能簡化編寫難度。

          所以,第一步就是編寫 eBPF 內(nèi)核態(tài)程序。

          使用 C 編寫 eBPF 程序

          新建一個 hello.c 文件,并輸入下面的內(nèi)容:

          int?hello_world(void?*ctx)
          {
          ????bpf_trace_printk("Hello,?World!");
          ????return?0;
          }

          使用 Python 和 BCC 工具開發(fā)一個用戶態(tài)程序

          新建一個 hello.py 文件,并輸入下面的內(nèi)容:

          #!/usr/bin/env?python3
          #?1)?加載?BCC?庫
          from?bcc?import?BPF

          #?2)?加載?eBPF?內(nèi)核態(tài)程序
          b?=?BPF(src_file="hello.c")

          #?3)?將?eBPF?程序掛載到?kprobe
          b.attach_kprobe(event="do_sys_openat2",?fn_name="hello_world")

          #?4)?讀取并且打印?eBPF?內(nèi)核態(tài)程序輸出的數(shù)據(jù)
          b.trace_print()

          下面我們來看看每一行代碼的具體含義:

          • 導(dǎo)入了 BCC 庫的 BPF 模塊,以便接下來調(diào)用。
          • 調(diào)用 BPF() 函數(shù)加載 eBPF 內(nèi)核態(tài)程序(也就是我們編寫的hello.c)。
          • 將 eBPF 程序掛載到內(nèi)核探針(簡稱 kprobe),其中?do_sys_openat2()?是系統(tǒng)調(diào)用?openat()?在內(nèi)核中的實現(xiàn)。
          • 讀取內(nèi)核調(diào)試文件?/sys/kernel/debug/tracing/trace_pipe?的內(nèi)容(bpf_trace_printk()?函數(shù)會將信息寫入到此文件),并打印到標(biāo)準(zhǔn)輸出中。

          運行 eBPF 程序

          用戶態(tài)程序開發(fā)完成之后,最后一步就是執(zhí)行它了。需要注意的是,eBPF 程序需要以?root?用戶來運行:

          $?sudo?python3?hello.py

          運行后,可以看到如下輸出:

          $?sudo?python3?hello.py
          b'?????????python3-31683???[001]?....?614653.225903:?0:?Hello,?World!'
          b'?????????python3-31683???[001]?....?614653.226093:?0:?Hello,?World!'
          b'?????????python3-31683???[001]?....?614653.226606:?0:?Hello,?World!'
          b'???????????<...>-31684???[000]?....?614654.387288:?0:?Hello,?World!'
          b'??????irqbalance-669?????[000]?....?614658.232433:?0:?Hello,?World!'
          ...

          到了這里,我們已經(jīng)成功開發(fā)并運行了第一個 eBPF 程序。當(dāng)然,這個程序很簡單,并且也沒有實際的用途。

          但通過這個程序,我們大概可以知道使用 BCC 開發(fā)一個 eBPF 程序的步驟。

          因為本系列文章并不是介紹如何開發(fā) eBPF 程序,而是介紹 eBPF 的原理和實現(xiàn)。如果大家有興趣學(xué)習(xí)如何開發(fā) eBPF 程序,那么建議大家看看《BPF性能之巔》這本書,這本書詳細(xì)地介紹了如何開發(fā) eBPF 程序。

          在下篇文章中,我們將介紹 eBPF 的實現(xiàn)原理,敬請期待。


          瀏覽 109
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  夜夜爽夜夜 | 久久大鸡巴 | 一区二区三区四区五区六区在线 | 大伊香蕉视频在线观看 | 手机毛片在线 |