eBPF 从入门到入门

本文介绍了eBPF(Extended Berkeley Packet Filter)的基础知识,包括其起源、与cBPF的区别,以及在现代操作系统中的重要作用。eBPF作为一个通用执行引擎,广泛应用于性能分析、网络过滤、内核调试等多个领域。文章详细阐述了eBPF的工作原理、架构,如虚拟机、指令集、字节码、hook、map和辅助函数等,并列举了BCC Tools、Cilium和eBPF Exporter等实际应用案例。此外,还提及了eBPF编程工具,如libbpf和bpftrace,以及其对内核模块的替代优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

eBPF 简介

什么是 BPF

BPF(Berkeley Packet Filter),中文翻译为伯克利包过滤器,是类 Unix 系统上数据链路层的一种原始接口,提供原始链路层封包的收发。BPF 在数据包过滤上引入了两大革新:

  • 基于虚拟机 (VM) 设计,可以有效地工作在基于寄存器结构的 CPU 之上。
  • 应用程序使用缓存只复制与过滤数据包相关的数据,不会复制数据包的所有信息。这样可以最大程度地减少BPF 处理的数据。

tcpdump就是采用 BPF 作为底层包过滤技术,我们可以在命令后面增加-d来查看tcpdump过滤条件的底层汇编指令。

$ tcpdump -d 'ip and tcp port 8080'
(000) ldh      [12]
(001) jeq      #0x800           jt 2	jf 12
(002) ldb      [23]
(003) jeq      #0x6             jt 4	jf 12
(004) ldh      [20]
(005) jset     #0x1fff          jt 12	jf 6
(006) ldxb     4*([14]&0xf)
(007) ldh      [x + 14]
(008) jeq      #0x1f90          jt 11	jf 9
(009) ldh      [x + 16]
(010) jeq      #0x1f90          jt 11	jf 12
(011) ret      #262144
(012) ret      #0

什么是 eBPF

2014 年初,Alexei Starovoitov 实现了 eBPF(extended Berkeley Packet Filter)。经过重新设计,eBPF 演进为一个通用执行引擎,可基于此开发性能分析工具、软件定义网络等诸多场景。eBPF 最早出现在 3.18 内核中,此后原来的 BPF 就被称为经典 BPF,缩写 cBPF(classic BPF),cBPF 虚拟机只在内核中可用,用于过滤网络数据包,与用户空间程序没有交互,因此被称为 “包过滤器”,而 eBPF 从内核空间扩展到用户空间,这也成为了 BPF 技术的转折点。

cBPF 已经基本废弃,现在,Linux 内核只运行 eBPF,内核会将加载的 cBPF 字节码透明地转换成 eBPF 再执行。没有特别说明,现在的 BPF 一般指的是 BPF 这项技术,而不再是任何首字母缩写词。

cBPF 和 eBPF 对比

eBPF 新的设计针对现代硬件进行了优化,所以 eBPF 生成的指令集比旧的 BPF 解释器生成的机器码执行得更快。扩展版本也增加了虚拟机中的寄存器数量,将原有的 2 个 32 位寄存器增加到 10 个 64 位寄存器。由于寄存器数量和宽度的增加,开发人员可以使用函数参数自由交换更多的信息,编写更复杂的程序。总之,这些改进使 eBPF 版本的速度比原来的 BPF 提高了 4 倍。

维度 cBPF eBPF
内核版本 Linux 2.1.75(1997年) Linux 3.18(2014年)[4.x for kprobe/uprobe/tracepoint/perf-event]
寄存器数目 2个:AX 10个:r0r9,另外r10是一个只读的帧指针
寄存器宽度 32位 64位
存储 16 个内存位: M[0–15] 512 字节堆栈,无限制大小的 “map” 存储
限制的内核调用 常有限,仅限于 JIT 特定 有限,通过 bpf_call() 指令调用
目标事件 数据包、 seccomp-BPF 数据包、内核函数、用户函数、跟踪点 PMCs 等

eBPF 与内核模块对比

eBPF 相比于直接修改内核和编写内核模块提供了一种新的内核可编程的选项。eBPF 程序架构强调安全性和稳定性,看上去很像内核模块,但与内核模块不同,eBPF 程序不需要重新编译内核,并且可以确保 eBPF 程序运行完成,而不会造成系统的崩溃。

维度 Linux 内核模块 eBPF
kprobes/tracepoints 支持 支持
安全性 可能引入安全漏洞或导致内核 Panic 通过验证器进行检查,可以保障内核安全
内核函数 可以调用内核函数 只能通过 BPF Helper 函数调用
编译性 需要编译内核 不需要编译内核,引入头文件即可
运行 基于相同内核运行 基于稳定 ABI 的 BPF 程序可以编译一次,各处运行
与应用程序交互 打印日志或文件 通过 perf_event 或 map 结构
数据结构丰富性 一般 丰富
入门门槛
升级 需要卸载和加载,可能导致处理流程中断 原子替换升级,不会造成处理流程中断
内核内置 视情况而定 内核内置支持

eBPF 可以用来做什么

一个 eBPF 程序会附加到指定的内核代码路径中,当执行该代码路径时,会执行对应的 eBPF 程序。鉴于它的起源,eBPF 特别适合编写网络程序,将该网络程序附加到网络 socket,进行流量过滤、流量分类以及执行网络分类器的动

eBPF(extended Berkeley Packet Filter)是一种在Linux内核中执行程序的技术,它可以用于网络分析、性能监控、安全审计等多种用途。下面是一个eBPF入门实践教程的大致步骤: 1. 确保你的系统支持eBPF:你需要一个运行Linux内核4.1或更高版本的机器,并且要启用eBPF功能。你可以通过运行`uname -r`命令来检查你的内核版本。 2. 安装所需的工具:你需要安装clang编译器、LLVM和libbpf库。这些工具可以帮助你编写和编译eBPF程序。你可以使用包管理器(如apt、yum等)来安装这些工具。 3. 学习eBPF原理:了解eBPF的基本概念和工作原理是很重要的。eBPF程序是一种在内核中执行的小型虚拟机程序,它可以通过钩子函数与内核交互并处理数据。 4. 编写eBPF程序:使用C语言编写eBPF程序,并使用clang编译器将其编译为eBPF字节码。eBPF程序可以通过BPF syscall加载到内核中。 5. 调试和测试:在运行eBPF程序之前,你可以使用bpftool和bpfsyscall等工具进行调试和测试。这些工具可以帮助你检查eBPF程序的正确性和性能。 6. 部署eBPF程序:一旦你的eBPF程序通过测试,你可以使用ip、tc等工具将其部署到实际的网络环境中。这些工具允许你在网络数据包到达内核之前或之后执行eBPF程序。 以上是一个简单的eBPF入门实践教程的大致步骤。在实际使用中,你可能会遇到更多的挑战和复杂性。但通过不断学习和实践,你将能够掌握eBPF技术并应用于各种场景中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值