作者 | 李阳,陈启钧
策划 | 田晓旭
首发 | InfoQ
eBPF 是 Linux 内核近几年最为引人注目的特性之一,通过一个内核内置的字节码虚拟机,完成数据包过滤、调用栈跟踪、耗时统计、热点分析等等高级功能,是 Linux 系统和 Linux 应用的功能 / 性能分析利器。本文将介绍 eBPF 的技术特点,及 eBPF 在网易杭研轻舟系统探测和网络性能优化方面的应用。
1. 技术浅析—eBPF 好在哪里
eBPF 是 Linux Kernel 3.15 中引入的全新设计,将原先的 BPF 发展成一个指令集更复杂、应用范围更广的“内核虚拟机”。
eBPF 支持在用户态将 C 语言编写的一小段“内核代码”注入到内核中运行,注入时要先用 llvm 编译得到使用 BPF 指令集的 ELF 文件,然后从 ELF 文件中解析出可以注入内核的部分,最后用 bpf_load_program() 方法完成注入。 用户态程序和注入到内核中的程序通过共用一个位于内核中的 eBPF MAP 实现通信。为了防止注入的代码导致内核崩溃,eBPF 会对注入的代码进行严格检查,拒绝不合格的代码的注入。
1.1 eBPF 的技术优势
eBPF 具备一些非常棒的特性,使得我们在内核层面的监控变得更加便捷、高效,并且非常安全:
- 平台无关,由 JIT 负责将 BPF 代码翻译成最终的处理器指令;
- 内核无关,辅助函数(Helper functions)使得 BPF 能够通过一组内核定义的函数调用(Function call)来从内核中查询数据,或者将数据推送到内核。不同类型的 BPF 程序能够使用的辅助函数可能是不同的;
- 安全检查,和内核模块不同,BPF 程序会被一个位于内核中的校验器(in-kernel verifier)进行校验,以确保它们不会造成内核崩溃、程序永远能够终止等;
- 方便升级,对于网络场景(例如 TC 和 XDP),BPF 程序可以在无需重启内核、系统服务或容器的情况下实现原子更新,并且不会导致网络中断;
- 通信方式,eBPF MAP,跟 Ftrace 提供的 ring buffer 相比就是数据常驻内存,不会读取之后就消失;
- 事件驱动,BPF 程序在内核中的执行总是事件驱动的;
1.2 eBPF 和其他 trace 工具的对比
在 eBPF 出现之前,Linux 已经存在多种成熟的 trace 机制和相应的上层工具:
如上图所示,eBPF 借助 perf_event 和 trace_event 几乎支持对目前所有已知 trace 功能的支持,唯一与传统 trace 工具不同的是,attach 到每个探测点的 probe 函数是