Linux:为什么性能工具需要 BPF 技术

爱学习的豆包 2021-01-23 15:14:22
linux Python tcpdump dwz


BPF是近年来Linux 系统技术领域一个巨大的创新。作为 Linux 内核的一个关键发展节点,其重要程度不亚于虚拟化、容器、SDN 等技术。

▼BPF 的工作方式十分有趣 :

最终用户使用 BPF 虚拟机的指令集(也称 BPF 字节码)定义过滤器表达式,然后传递给内核,由解释器执行。这使得包过滤可以在内核中直接进行,避免了向用户态进程复制每个数据包,从而提升了数据包过滤的性能,tcpdump(8) 就是这样工作的。

BPF 还提供了安全性保障,因为用户定义的过滤器在执行前必须首先通过安全性验证。

早期的包过滤必须在内核空间执行,安全是一个硬性要求。大家可以从下图了解这一切是如何工作的。

file

tcpdump 和 BPF

在运行 tcpdump(8) 时带上命令行参数 -d,可以打印出使用过滤器表达式的 BPF 指令。例如 :



▊** 经典 BPF 与扩展版 BPF**

最初的 BPF 现在被称为“经典 BPF”,它是一个功能有限的虚拟机。它有两个寄存器,一个由 16 个内存槽位组成的临时存储区域和一个程序计数器。以上部件均按 32 位寄存器大小运行。经典 BPF 于 1997 年进入 Linux 内核版本 2.1.75。

而后Alexei Starovoitov 创造了扩展版 BPF(eBPF)。这是 20 年来 BPF 的第一次重大更新,此举也将 BPF 扩展为一个通用的虚拟机。

虽然BPF通常被称为虚拟机,不过这往往指的是它的实现规范。BPF在Linux中的实际实现(运行时支持)同时包括一个解释器和一个可即时编译为本机指令的编译器。

“虚拟机”一词似乎意味着在处理器之上运行另一个机器层,而实际BPF执行并非如此。JIT编译后的代码会像任何其他本地内核代码一样,直接在处理器上运行。要注意,在Spectre漏洞公布之后,一些发行版默认在x86架构上启用JIT,完全移除了内核中的解释器实现(通过条件编译直接排除了相关代码)。

扩展版的 BPF 中增加了更多寄存器,并将字长从 32 位增至 64 位,创建了灵活的BPF 映射型存储(map),并允许调用一些受限制的内核功能。同时,eBPF 被设计为可以使用即时编译(JIT),机器指令与寄存器可以一对一映射。这就使得先前的处理器本地指令优化技术,可以重用于 BPF 之上。BPF 验证器也进行了更新以便支持这些扩展,而且能够拒绝任何不安全的代码。

经典 BPF 和扩展版 BPF 之间的差异如下。

file

在最早的代码补丁中,扩展版BPF曾被简写为 eBPF,不过如今有关的开发讨论中,都直接使用BPF 这种叫法。

Linux BPF 运行时(runtime)的各模块的架构如下图。

file

BPF 运行时的内部结构

上图展示了 BPF 指令如何通过 BPF 验证器验证,再由 BPF 虚拟机执行。

BPF 虚拟机的实现既包括一个解释器,又包括一个 JIT 编译器 :JIT 编译器负责生成处理器可直接执行的机器指令。验证器会拒绝那些不安全的操作,这包括针对无界循环的检查 :BPF 程序必须在有限的时间内完成。

BPF 可以利用辅助函数获取内核状态,利用 BPF 映射表进行存储。BPF 程序在特定事件发生时执行,包括 kprobes、uprobes 和跟踪点等事件。

接下来我们来讨论一下,为什么性能工具需要 BPF 技术。

为什么性能工具需要 BPF 技术

性能工具使用扩展版 BPF 来实现可编程性。BPF 程序可以执行自定义的延迟计算和统计摘要等功能。这些特性本身就足够使 BPF 成为一个有趣的工具。

不过事实上有很多跟踪工具都具备了这些功能。BPF 与众不同之处在于,它还同时具备高效率和生产环境安全性的特点,并且它已经被内置在 Linux 内核中。

有了 BPF,你就可以在生产环境中直接运行这些工具,而无须增加新的内核组件

下面我们通过一个工具的输出和一幅图来看一下性能工具是如何使用 BPF 的。

这个 例子的输出来自性能优化大师Gregg以前发布的一个叫作 bitehist 的 BPF 工具,它用直方图的形式展示磁盘 I/O 的尺寸分布:

file

下图显示了使用 BPF 之前和之后的直方图生成过程。

file

使用 BPF 之前和之后生成直方图过程的对比

这里的关键变化是,直方图可以在内核上下文中生成,这大大减少了需要复制到用户空间的数据量。这里的效率提升是如此的显著,以至于工具的额外开销减小到可以在生产环境下直接运行的程度。

使用 BPF 之前,制作这一直方图摘要的最佳步骤如下。

1.在内核中 :开启磁盘 I/O 事件的插桩观测。

2.在内核中,针对每个事件 :向 perf 缓冲区写入一条记录。如果使用了跟踪点技术(推荐方式),记录中会包含关于磁盘 I/O 的几个元数据字段。

  1. 在用户空间 :周期性地将所有事件的缓冲区内容复制到用户空间。

  2. 在用户空间 :遍历每个事件,解析字节字段的事件元数据字段。其他字段会被忽略。

  3. 在用户空间 :生成字节字段的直方图摘要

其中步骤 2 到步骤 4 对于高 I/O 的系统来说性能开销非常大。可以想象一下,将 10000个磁盘 I/O 跟踪记录复制到用户空间程序中,然后解析以生成摘要信息—每秒执行 1 次。

使用 BPF 之后,bitesize 程序执行的步骤如下。

  1. 在内核中:启用磁盘 I/O 事件的插桩观测,并挂载一个由 bitesize 工具定义的BPF 程序。

  2. 在内核中,对每次事件 :运行 BPF 程序。它只获取字节字段,并将其保存到自定义的 BPF 直方图映射数据结构中。

3.在用户空间 :一次性读取 BPF 直方图映射表并输出结果。

这个过程避免了将事件复制到用户空间并再次对其处理的成本,也避免了对未使用的元数据字段的复制。如前面的程序输出截图所示,唯一需要复制到用户空间的数据是“count”列,其是一个数字数组。

▊ BPF 与内核模块的对比

还有一种方法可以理解 BPF 在可观测性方面的优势 :将其与内核模块进行比较。

kprobes 和跟踪点已经出现多年了,可以直接从可加载的内核模块中使用。与使用内核模块相比,使用 BPF 进行跟踪的优势如下 :

● BPF 程序会通过验证器的安全性检查 ;内核模块则可能会引入 bug(内核崩溃)或安全漏洞。

● BPF 通过映射提供丰富的数据结构支持。

● BPF 程序可以一次编译,然后在任何地方运行,因为 BPF 指令集、映射表结构、辅助函数和相关基础设施属于稳定的 ABI。(当然,有些 BPF 程序包含了不稳定的因素,比如使用了 kprobes 来观测内核数据结构,这会影响 BPF 程序的自身稳定性)

● BPF 程序的编译不依赖内核编译过程的中间结果。

● 与开发内核模块所需的工程量相比,BPF 编程更加易学,可以让更多人上手。

请注意,在网络领域应用 BPF 还有额外的好处,包括原子性替换 BPF 程序的能力。如果使用内核模块,则需要先从内核中将其完全卸载,然后再次加载,这可能会导致相关服务中断。

使用内核模块的一个好处是 :在模块中可以使用其他内核函数和内核设施,而不仅限于 BPF 提供的辅助函数。

不过,如果调用任意内核函数的能力被滥用,也会带来引入bug 的额外风险。

文:博文观点 | 转自:InfoQ [拿走不谢!Python 3.9 官方中文文档,限时领!] (http://dwz.date/dE6v)

[限时!速领!14张高清Python速查表,效率提升必备!] (http://dwz.date/dE6w)

[GitHub标星3W+,80个Python案例,带你轻松玩转Python学习!] (http://dwz.date/dE64)

版权声明
本文为[爱学习的豆包]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/4630617/blog/4921456

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云