LWN:在今后十年让BPF保持活力!

关注了就能看到更多这么棒的文章哦~

Modernizing BPF for the next 10 years

By Daroc Alden
June 7, 2024
LSFMM+BPF
Gemini-1.5-flash translation
https://lwn.net/Articles/977013/

BPF 最初 采用来作为对数据包过滤的一个通用化处理方案,这发生在十多年前。在那之后,BPF 发生了巨大的改变,变得更加强大。Alexei Starovoitov 在 2024 年 Linux 存储、文件系统、内存管理和 BPF 峰会 的第二天以 BPF 主题的演讲拉开了序幕,他带领大家讨论了 BPF 在未来十年不断发展过程中将要发生哪些变化。他提出了几个想法,包括扩展 BPF 程序可用的寄存器数量、动态死锁检测以及放宽验证器的一些现有限制。

Starovoitov 从回顾过去十年 BPF 发展的历程开始。BPF 最初的应用场景是在网络部分 —— 因此得名 "Berkeley Packet Filters"。2015 年,BPF 扩展成为了新一代工具,包括用于追踪(tracing)。他说道,BPF 中的一切演变都有其原因。一旦内核中存在对 BPF 的支持,像 katran 和 Cilium 之类的用户空间工具就开始出现并利用它。

3b308369f922777c986ae6b5126ffbeb.png

随着追踪工具的演变,它们需要访问内核头文件,以便理解它们看到的数据是如何布局的。他解释说,这引出了 BPF 类型格式 (BPF Type Format, BTF),“一次编译——到处运行”(CO-RE),以及教会 Clang 如何进行符号字段访问而不是使用已知的偏移量。也引入了其他一些增强 BPF 易用性的功能被引入进来。

在 C 语言中,全局变量的自然表示是将它们存储在 .data 段(或 .bss=、 =.rodata 等)中。但是,对于 BPF 程序来说,将全局变量与用户空间共享以进行配置或报告通常更有意义,这意味着数据需要存储在 BPF 映射(mapping)中。然而,即使全局变量存储在 BPF 映射中,用户空间可能仍然不知道它们的排列方式。解决方案是 BPF 的 骨架支持(skeleton support),它按照编译器布局全局变量相匹配的方式来生成类型(types),使其更易于以编程方式访问。

BPF 代码的编写方式也发生了很大的变化。最初,验证器不支持函数调用——这意味着程序员必须用 always_inline 来注释所有函数。这已经不再需要了,但由于互联网上存在各种旧的示例,许多用户似乎并不知道这一点。Starovoitov 说:“我觉得我们需要在宣传最佳实践方面多做一些。”循环也是类似的情况;它们最初不受支持,但随着时间的推移,它们变得越来越可用。然而,今天仍然有补丁提交到邮件列表中是使用 bpf_loop() 的,尽管 开放式迭代器(open-coded iterators, 更好的一个替代方案)在两年前就已经添加了。

BPF 代码使用的接口也发生了一些变化。BPF 调用内核代码的机制,最开始是靠辅助函数的。这些被认为是稳定的接口,因此很难尝试新的可能性。它们后来得到了 kfunc 作为补充,kfunc 是一个不稳定的接口,可以从任何地方扩展,包括内核模块。在 Starovoitov 演讲时,内核中存在 211 个辅助函数和 164 个 kfunc。

对于内核代码调用 BPF, struct_ops 机制提供了相同的灵活性。该特性最初是为 sched_ext 引入的,但事实证明它在内核中拥有许多用户。Starovoitov 说,实现该特性确实花费了一些时间,因为对 BPF 调用约定的必要转换并不简单。但总的来说, struct_ops 一直是一个非常有用的特性。

它也不是由 sched_ext 推动的 BPF 唯一改变;与调度器的必要集成意味着它推动了许多功能,这些功能可以改善内核和 BPF 程序之间的数据共享。最值得注意的也许是 kptrs,它们是指向内核数据结构的直接指针,依赖于 BPF 验证器来跟踪所有权和生命周期信息。

当然,总的趋势是让 BPF 程序更强大。Starovoitov 讨论的最近变化是 BPF arenas 和 cond_break,它们代表着 BPF 能够实现任意算法和数据结构的一大步。Starovoitov 说,添加这些意味着扩展 BPF 不再需要那么多的内核更改,它还将许多静态验证转化为运行时验证。现在这些功能已经到位,将会出现更多 BPF 库。正则表达式和哈希表的库已经存在——字符串操作库可能是下一个。

未来

现在,库代码(library code)通过最古老的库管理技术在 BPF 程序之间重复使用,那就是复制和粘贴。他说道,这需要改变。BPF 开发人员需要一些方法将共享 BPF 代码作为库进行分发——理想情况下,一种类似于 Rust 或 Python 的方法,其中库仅作为源代码进行分发。C 和 C++ 并不真正擅长处理依赖关系管理,BPF 应该吸取它们的教训。

并非所有理想的库都可以在今天的 BPF 中编写;为了实现真正任意的算法,还需要一些额外的增强。 sched_ext 无法完成用户可能想要的所有事情——尤其是重新实现 EEVDF(当前的默认 Linux 调度器)——因为当前对锁的限制。一次只能持有单个锁,并且程序在持有锁时不能调用 kfunc。更糟糕的是,验证器代码中的错误可能会在这种情况下导致死锁。Starovoitov 断言,BPF 需要另一道防线,以便 BPF 程序(或 BPF VM 的核心基础设施)持有的锁不能干扰内核。一旦这一点成为可能,就可以实现运行时死锁检测,然后就可以放宽验证器目前对锁的限制。

很多人认为放宽验证器的要求是让 BPF 图灵完备的必要条件,但与普遍看法相反,它已经图灵完备了,他说道。BPF arena 几乎是最后一个需要为此补上的功能,之后可以在 BPF 中实现解释器来证明这一点。唯一缺少的部分是对跳转表和间接 gotos 的支持。Starovoitov 解释说,在 BPF 中编写解释器是一个“玩具动机”,他并不期望任何人真的想去这样做,但跳转表是 BPF 要想有所作为的必要条件。

与间接 gotos 相关的是对尾调用(tail calls)支持。BPF 已经拥有 bpf_tail_call() ,但 Starovoitov 称之为一个 hack,说它使用起来很麻烦。一个更简洁的解决方案是使用一个专门的指令进行间接调用——BPF 从一开始实际上就拥有它,只要调用目标是全局函数。缺少的组件是验证器尚未支持;需要更改验证器以理解“指令地址”的概念。

效率

让 BPF 更灵活的目标几乎不需要其他功能,但也还有一些可以提高效率的功能,比如专用的 bit 操作指令或对调用约定(calling convention)的改动,Starovoitov 解释道。特别是,一个函数属性可以用来标记不需要使用调用者保存寄存器的函数,这可以让编译器更智能地分配寄存器,并减少溢出到堆栈的寄存器数量。另一个关于更好地分配寄存器的可能想法是仅仅增加可用寄存器的数量。当 BPF 最初被开发时,x86 是正在考虑的主要架构;与其他架构相比,它提供的寄存器数量不多。对于现代 BPF 来说,Arm 和 RISC-V 架构是重要的竞争者——但 BPF 程序无法利用到增加了的可用寄存器数量。

Starovoitov 提到了 BPF 开发人员可以用来解决这个问题的几种方法,比如切换到虚拟寄存器并在内核中进行寄存器分配。其他可能性包括拒绝对给定架构使用太多寄存器的程序、为不同数量的寄存器编译的臃肿的二进制文件,或者让验证器跟踪溢出到堆栈的寄存器,并在可能的情况下将其转换为寄存器。David Vernet 指出,BPF 的指令编码只有 4 位用于寄存器,因此使用超过 16 个寄存器将很困难。Starovoitov 回复说,新的指令可能会为寄存器增加更多空间,并指出他认为对寄存器数量的限制已经过时了。

增加可用寄存器的数量也可能为传递六个或更多参数打开大门。现在,BPF 每个函数最多可以传递五个参数,因为只有五个寄存器用于传递参数。可以通过使用堆栈来解决这个问题,但额外的寄存器将是一个更简单的解决方案。改变 BPF 调用约定的关键点是要确保它可以有效地映射到内核的调用约定,因此正确的解决方案并不立即显而易见。

更多用途

Starovoitov 提到了一个最终的“空中楼阁”的想法,用于改善 BPF 和内核之间的互操作性:有了额外的寄存器和扩展的调用约定,就可以做到将内核编译成 BPF ISA。这将为许多以前无法想象的应用程序打开大门,例如在整个内核中使用 BPF 调试。

但也有一些更可行的改进,比如允许 alloca()。BPF 程序目前被限制为 512 字节的堆栈,这使得使用 alloca() 不切实际,因为没有太多空间可用于分配。虽然可能可以扩展 BPF 堆栈的大小,但另一个解决方案是使用“分隔堆栈(divided stack)”,该堆栈在单独的堆栈上跟踪返回地址和局部变量。内核能看到的 512 字节堆栈可以用来保存函数调用,并在运行时动态分配更大的堆栈(可能在 BPF arena 内)。

Vernet 质疑在 BPF 程序中 alloca() 有多令人满意,并指出与使用静态分配相比,它会创建一堆额外的指令——事实上, alloca() 在内核中是被禁止的,原因之一就是这个。Starovoitov 承认它在内核中是被禁止的,但他不认为这跟 BPF 程序有什么关系。 alloca() 比堆分配开销要小得多,并且可以保证成功。BPF 程序可能会发现它对保存大小根据内核结构的大小而变化的结构很有用,这是一个相当频繁会遇到的麻烦问题。

当然,所有这些未来的灵活性都需要付出代价。Starovoitov 说:“并非所有事情都可以静态完成。” 让 BPF 程序安全地取消,并使用运行时超时来增强程序验证,这些可能会变得必要。Starovoitov 说,这项工作正在进行中。但是,调试所有这些新功能不太可能成为问题,因为 BPF 已经具有良好的可观察性。BTF 调试信息非常适合 C 代码(以及内核代码),现有的工具,比如 bpftrace,非常有效地利用了它。缺少的一件事是让这些可观察性工具在用户空间工作。Starovoitov 指出这是一个“先有鸡还是先有蛋”的问题:用户模式 BPF 探测器速度不快,所以为什么要费心支持它们?但是,如果没有额外的支持,它们就不会变得更快。此外,用户空间使用的许多语言与 BTF 语义不匹配,这可能需要对格式进行更改。

让 BPF 更强大的一个潜在副作用是让验证器承担更多工作。目前,验证器有一个百万条指令的限制,仅仅是为了限制它在一个病态的 BPF 程序上花费的时间。但是,对于大型程序来说,任何验证器或编译器的更改都可能让它达到这个限制,这是一种“糟糕的用户体验”。Starovoitov 说,目前还没有真正的解决方案,但这个问题是 BPF 开发人员必须有意识地关注以解决的问题。有一些解决方法,比如在 BPF CI 中测试编译器的更改。另一个可能的解决方案是放宽限制,让验证器在它能够判断它正在取得进展的情况下不受一百万条指令的限制。

Starovoitov 提出的最后一个想法是将 BPF 打造成一个内核模块。他指出,对于销售需要 BPF 的产品的供应商来说,主要问题是使用的内核种类繁多;很难让一个 BPF 程序在所有内核上都能正常工作。他解释说,一个潜在的解决方案是使 BPF 子系统能够独立于基本内核进行升级。这本身将是一个巨大的挑战——现有的内核模块机制不足以支持它——但它可以解决一些持久的问题(persistent problems)。

问题

Starovoitov 在结束演讲时说,他认为 BPF 的下一个增长领域可能是 Linux 安全模块 (LSM)、其他安全用例,以及对 sched_ext 的持续改进。观众提出了一些问题。一个人问 Starovoitov 认为 BPF 在经过十年的变化之后,现在用起来更容易还是更难。Starovoitov 回复说,BPF 开发人员已经使其更容易使用,但他们实际上无法简化 BPF 背后的某些核心设计,因为受限于稳定性保证,它并不像它原本可以做到的那样容易使用。另一个人问 Starovoitov 是否期望 BPF 在内核之外看到增长。Starovoitov 回复说,BPF 的主要力量在于可观察性和安全性。内核之外可能有一些用例需要这种组合,但用户空间整体上不会从 BPF 中受益,他说道。

另一位观众询问如何将所有这些信息传达给没有出席 LFSMM+BPF 的众多 BPF 用户;他们建议开展对外推广,向其他会议推广这些想法。Starovoitov 说,他完全同意这是一个好主意,但他不是做福音传教的专家。他呼吁会议上的其他人帮助宣传这些想法。

BPF 的增长速度惊人,而且没有任何迹象表明它会停止。许多用户正在发现 BPF 带给内核的更强的可观察性和可配置性所带来的价值。与此同时,很明显,人们仍然有很大的计划来改变 BPF。在未来的十年中,它可能会有很大的不同。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

45805d42bbd4c765f70694a46d20e8fa.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值