LWN:BPF與io_uring的結(jié)合!
關(guān)注了就能看到更多這么棒的文章哦~
BPF meets io_uring
By Jonathan Corbet
March 4, 2021
DeepL assisted translation
https://lwn.net/Articles/847951/
過(guò)去幾年,很多開(kāi)發(fā)工作是圍繞著 BPF 和 io_uring 的。BPF 虛擬機(jī)允許在 kernel 上下文中安全地運(yùn)行來(lái)自用戶空間的程序, 而 io_uring 則解決了長(zhǎng)期以來(lái)異步運(yùn)行系統(tǒng)調(diào)用的需求。隨著這兩個(gè)子系統(tǒng)的不斷擴(kuò)充,兩者最終不可避免地發(fā)生了交匯。第一次交匯就發(fā)生在 2 月中旬,Pavel Begunkov 提出的 這組patch 增加了從 io_uring 內(nèi)運(yùn)行 BPF program 的功能。
這組 patch 本身比較簡(jiǎn)單,僅僅新增加了不到 300 行代碼。它為那些需要在 io_uring 上下文中運(yùn)行的 BPF program 創(chuàng)建了一個(gè)新的 BPF program type (BPF_PROG_TYPE_IOURING)。任何此類(lèi) program 都必須首先用 bpf() 系統(tǒng)調(diào)用來(lái)創(chuàng)建,然后使用新增的 IORING_ATTACH_BPF 命令將它們注冊(cè)到 ring 中等待運(yùn)行。完成了這些工作之后,IORING_OP_BPF 這個(gè)操作就會(huì)在 ring 內(nèi)真正運(yùn)行 program。這組 patch 最后一步增加了一個(gè) helper function,BPF program 可以使用該函數(shù)向 ring 中提交新的操作。
這組 patch 展示了如何從 io_uring 中運(yùn)行 BPF program,這給我們大家建立了直觀的第一印象。不過(guò),這組 patch 實(shí)際上并沒(méi)有真正實(shí)現(xiàn)什么此前無(wú)法做到的新功能,這可能就是為什么在 mailing list 中沒(méi)有任何回應(yīng)的一部分原因了。異步運(yùn)行一個(gè) BPF program 來(lái)提交另一個(gè)操作,這種做法的價(jià)值不大,畢竟人們可以直接提交那個(gè)操作就好。正如 patch set 中所承認(rèn)的,要想讓這個(gè)功能對(duì)用戶真正有用,還需要先實(shí)現(xiàn)更多的基礎(chǔ)設(shè)施(infrastructure)。
BPF 在這種場(chǎng)景中,如果可以根據(jù)之前操作的結(jié)果來(lái)做出決策的話,就真正可以增加價(jià)值了。目前都是必須在用戶空間中做決策的,這就會(huì)對(duì)受這個(gè)決策進(jìn)程合適得到 schedule 以及執(zhí)行的影響,從而可能增加延遲。當(dāng)某個(gè)操作完成后,在不退出 kernel mode 的情況下由一個(gè) BPF program 來(lái)決定接下來(lái)執(zhí)行哪個(gè)操作,這就會(huì)很有用處了。"下一步做什么" 包括可以提交更多的 I/O 操作到 ring 中、繼續(xù)處理一系列文件中的下一個(gè)、或者在發(fā)生意外情況時(shí)中止一系列命令。
要能做決策的話,就需要能夠根據(jù) ring 中的其他事件來(lái)相應(yīng)地執(zhí)行 BPF program。現(xiàn)在 io_uring 中已經(jīng)具有的順序執(zhí)行機(jī)制足以保證在某個(gè)特定操作完成之后來(lái)運(yùn)行某個(gè) program,但這個(gè) program 無(wú)法獲得關(guān)于之前這個(gè)操作的完成情況的更多有用信息。正如 Begunkov 所指出的那樣,要解決這個(gè)問(wèn)題,就需要有一種方法能在在運(yùn)行一個(gè) BPF program 時(shí),將上一個(gè)操作的結(jié)果傳遞給它。還有一種方案是將 program 與某個(gè)已經(jīng)提交的操作綁定(而不是像補(bǔ)丁集中那樣將它們變成單獨(dú)的操作)起來(lái)從而在這些操作完成時(shí)運(yùn)行到這個(gè) BPF program。
等擁有了這個(gè)功能之后,加上 io_uring 內(nèi)已經(jīng)支持了越來(lái)越多的系統(tǒng)調(diào)用,那么就可以創(chuàng)建出復(fù)雜的、與 I/O 相關(guān)的、能在內(nèi)核空間長(zhǎng)時(shí)間運(yùn)行的 program。運(yùn)行 BPF program 看似是對(duì) io_uring 的增強(qiáng),但也可以看作是賦予了 BPF 執(zhí)行 I/O 和各種系統(tǒng)調(diào)用的能力。這個(gè)組合很可能可以讓人們利用它們來(lái)做出一些令人驚訝的事情。
當(dāng)然,這不是一個(gè)會(huì)被廣泛使用的功能。就其本身而言,io_uring 帶來(lái)了一定程度的復(fù)雜性,只有對(duì)于那些可以從異步處理中獲得顯著性能提升的場(chǎng)景才會(huì)用到它。將 BPF 加入到這個(gè)組合中將大大增加復(fù)雜程度,而且很長(zhǎng)一串系列操作以及 BPF program 在調(diào)試時(shí)會(huì)是非常具有挑戰(zhàn)性的。最后,要加載 io_uring program 就需要擁有 CAP_BPF 或 CAP_SYS_ADMIN,這意味著在大多數(shù)環(huán)境中都需要 "root" 權(quán)限。只要目前對(duì) unprivileged BPF program 的反對(duì)仍然存在,那么這里就是個(gè)死結(jié)。因此,只會(huì)有非常少的程序會(huì)利用這個(gè)功能。
不過(guò),這兩個(gè)子系統(tǒng)的結(jié)合還是為 Linux 未來(lái)的發(fā)展提供了一個(gè)有趣的前景。Linux(很可能)永遠(yuǎn)不會(huì)是一個(gè) unikernel 系統(tǒng),但用戶空間和內(nèi)核之間的界限似乎確實(shí)越來(lái)越模糊。
全文完
LWN 文章遵循 CC BY-SA 4.0 許可協(xié)議。
長(zhǎng)按下面二維碼關(guān)注,關(guān)注 LWN 深度文章以及開(kāi)源社區(qū)的各種新近言論~
