-10 +

ebpf 介绍 2

ebpf

接上文ebpf的介绍,我们继续聊. ebpf 由以下几个模块组成

RISC Instruction Set

ebpf 被设计为一个 RISC 精简指令集,可以使用 C 语言子集合编写,通过编译器(LLVM)编译。 随后 linux kernel 可以很简单的通过 JIT 编译 ebpf 程序为 native code 在各种 cpu 上执行, 这样可以保证 ebpf 的性能。这样设计的优点有:

ebpf 程序总是通过 event-driven 来运行的。

ebpf 包含 11 个寄存器,一个 512 字节的 stack space。

ebpf 程序的一些限制

Helper Functions

eBPF 不能直接调用 kernel 的函数,因为这么做会导致 eBPF 会和 kernel 的版本绑定, 导致向下兼容非常困难,调用 kernel 函数的能力是通过 helper functions 来实现的, 这样通过保证 helper functions 的 ABI 的稳定性来保证 eBPF 的向下兼容性。

Maps

map 是一个高性能 key/value 存储系统,这个是在 linux kernel 中实现的。 map 的主要用途是在 ebpf 和 ebpf,以及 ebpf 和 应用程序中共享数据。 当前一个 ebpf 能使用 64 中不同类型的 map。

Others

eBPF Safety

通过上面的介绍的可以知道 eBPF 是一种可编程的 kernel 技术,那么如果 eBPF 不安全将影响 kernel 的稳定性。 eBPF 是通过下面的手段来保证 eBPF 程序对于 kernel 是安全的。

Required Privileges

只有 privileged mode (root)/capability CAP_BPF 权限的程序来能 load 和 run eBPF 程序。

Verifier

当 eBPF 程序被加载后,会通过 eBPF verifier 来校验 eBPF 程序是否满足以下要求

Hardening

Abstracted Runtime Context

eBPF 不能直接访问 kernel 中的任意内存,只能通过 helper function 来访问上下文之外的数据。 如果在安全的条件, eBPF 程序能够修改某些数据。

Object Pinning

ebpf 程序和 map 本质上都是 linux kernel 中的一个种资源。 当 ebpf 需要和其他 ebpf 或者 应用程序共享这些资源时,可以通过 linux 的文件描述符来通信。 但是这个缺点也是明显的,比如用 tc 加载的 ebpf 程序,tc 加载完毕,生命周期也就结束了, 这时 map 资源无法被外部的用户应用程序共享。所以 linux kernel 实现一个最小集合的文件系统。 这个文件系统就是 object pinning,通过这个技术就可以使用 linux 匿名文件系统来访问这些资源。

Tail Calls

如图所示,tail calls 是一种 ebpf 程序调用另外一个 ebpf 程序,但是这个调用不像普通的函数调用, tail calls 不会返回上一级调用,并且没有普通函数调用的寄存器 push/put 消耗,看起来就是一次 long jump, 两个 ebpf 函数使用的是同一个栈空间。 使用 ebpf tail call 技术,只需要做以下两点

kernel 将直接运行 BPF_MAP_TYPE_PROG_ARRAY 中指令,BPF_MAP_TYPE_PROG_ARRAY 对于 user space 是只写的。

BPF to BPF Calls

JIT

Offloads

参考

关于我

85 后程序员, 比较熟悉 Java,JVM,Golang 相关技术栈, 关注 Liunx kernel,目前痴迷于分布式系统的设计和实践。 研究包括但不限于 Docker Kubernetes eBPF 等相关技术。

Blog

Code

Life

Archive