ebpf发展简史
前言
极客时间 eBPF 核心技术与实战 的学习笔记.
本章简单介绍一下 eBPF 的发展和概述
eBPF发展历史
注意区分 BPF 和 eBPF
提案
1992年 USENUX 会议上提出BPF机制来在 linux 中进行包过滤
- 在内核态中引入虚拟机执行 BPF 指令
- 在用户态使用 BPF 字节码来进行表达式的自定义, 然后交由内核态中的虚拟机来执行
- 因为直接在内核态进行过滤, 避免了每个包都复制到用户态, 相比传统方式提高了性能
加入
linux 2.1.75(1997年)版本中首次引入了 BPF 技术
linux 3.0(2011年)替换了原先的 BPF 解释器,进一步提升了运行效率
eBPF
linux 3.18(2014年) BPF 升级为 eBPF, 将BPF虚拟机由原来的包过滤功能扩大到支持通用功能
linux 4.x 继续迭代 eBPF, 先后支持了 函数/跟踪点/性能事件/安全控制 等, eBPF快速发展
eBPF 工作方式
eBPF只有在需要触发时(事件触发)才会执行, 比如 系统调用/网络事件 等等, 现如今, eBPF 几乎可以在系统的任意部分进行插桩
运行流程
- 将 eBPF 程序转换成 BPF 字节码
- BPF 系统接受到 BPF 字节码
- BPF 系统检查 BPF 字节码是否安全和可靠(避免影响系统正常运行)
- 提交到即时编译器执行
典型的不安全程序逻辑
- 包含无限循环
- 可能导致内核崩溃
- 在有限时间内不能运行完成
数据传输
用户编写的 eBPF 程序一般分为两部分, 在用户态运行的部分负责逻辑处理, 而在内核态运行的部分负责对数据进行抓取和简单筛选, 而后传输给用户态部分.
如何在两个态之间进行数据的传输? 答案是 BPF 映射(map)
eBPF限制
常见的 eBPF 限制
- eBPF程序必须经过安全性校验, 验证失败则不允许执行
- 必须是特权进程执行
- 不能随意调用系统内核函数, 只能调用在 BPF 系统中定义的 API
- eBPF 自带的栈空间只有512字节, 想要更大的存储, 只能使用 map(BPF 映射)
- linux 内核的升级, 可能会导致之前的eBPF 程序运行错误, 可能需要调整源码或者重新编译
- eBPF 程序最好在 linux内核版本大于 4.9 以上的系统运行, 最好是 5.x 及以上(截止到2024年12月1日, linux内核的稳定版本是 6.12.1)