首页 > 其他分享 >eBPF是如何工作的

eBPF是如何工作的

时间:2024-02-01 22:02:01浏览次数:25  
标签:字节 映射 BPF eBPF 程序 工作 如何 内核

eBPF 全称“扩展的伯克利数据包过滤器 (Extended Berkeley Packet Filter)” 来看,它是一种数据包过滤技术,是从 BPF (Berkeley Packet Filter) 技术扩展而来的。

BPF 提供了一种在内核事件和用户程序事件发生时安全注入代码的机制,这就让非内核开发人员也可以对内核进行控制。随着内核的发展,BPF 逐步从最初的数据包过滤扩展到了网络、内核、安全、跟踪等,而且它的功能特性还在快速发展中,这种扩展后的 BPF 被简称为 eBPF(相应的,早期的 BPF 被称为经典 BPF,简称 cBPF)。实际上,现代内核所运行的都是 eBPF。

在 eBPF 之前,内核模块是注入内核的最主要机制。由于缺乏对内核模块的安全控制,内核的基本功能很容易被一个有缺陷的内核模块破坏。而 eBPF 则借助即时编译器(JIT),在内核中运行了一个虚拟机,保证只有被验证安全的 eBPF 指令才会被内核执行。同时,因为 eBPF 指令依然运行在内核中,无需向用户态复制数据,这就大大提高了事件处理的效率。

eBPF是如何工作的_eBPF

eBPF 程序并不像常规的线程那样,启动后就一直运行在那里,它需要事件触发后才会执行。这些事件包括系统调用、内核跟踪点、内核函数和用户态函数的调用退出、网络事件,等等。借助于强大的内核态插桩(kprobe)和用户态插桩(uprobe),eBPF 程序几乎可以在内核和应用的任意位置进行插桩。

通常我们借助 LLVM 把编写的 eBPF 程序转换为 BPF 字节码,然后再通过 bpf 系统调用提交给内核执行。内核在接受 BPF 字节码之前,会首先通过验证器对字节码进行校验,只有校验通过的 BPF 字节码才会提交到即时编译器执行。

eBPF是如何工作的_eBPF_02

如果 BPF 字节码中包含了不安全的操作,验证器会直接拒绝 BPF 程序的执行。比如,下面就是一些典型的验证过程:

  • 只有特权进程才可以执行 bpf 系统调用;
  • BPF 程序不能包含无限循环;
  • BPF 程序不能导致内核崩溃;
  • BPF 程序必须在有限时间内完成。

BPF 程序可以利用 BPF 映射(map)进行存储,而用户程序通常也需要通过 BPF 映射同运行在内核中的 BPF 程序进行交互。如下图所示,在性能观测中,BPF 程序收集内核运行状态存储在映射中,用户程序再从映射中读出这些状态。

eBPF是如何工作的_eBPF_03

可以看到,eBPF 程序的运行需要历经编译、加载、验证和内核态执行等过程,而用户态程序则需要借助 BPF 映射来获取内核态 eBPF 程序的运行状态。

eBPF 并不是万能的,它也有很多的局限性。下面是一些最常见的  eBPF 限制:

  • eBPF 程序必须被验证器校验通过后才能执行,且不能包含无法到达的指令;
  • eBPF 程序不能随意调用内核函数,只能调用在 API 中定义的辅助函数;
  • eBPF 程序栈空间最多只有 512 字节,想要更大的存储,就必须要借助映射存储;
  • 在内核 5.2 之前,eBPF 字节码最多只支持 4096 条指令,而 5.2 内核把这个限制提高到了 100 万条;
  • 由于内核的快速变化,在不同版本内核中运行时,需要访问内核数据结构的 eBPF 程序很可能需要调整源码,并重新编译。

想要稳定运行 eBPF 程序,内核版本至少需要 4.9 或者更新。而在开发和学习 eBPF 时,为了体验最新的 eBPF 特性,推荐使用更新的 5.x 内核。

标签:字节,映射,BPF,eBPF,程序,工作,如何,内核
From: https://blog.51cto.com/key3feng/9536532

相关文章

  • # yyds干货盘点 # Pandas中如何删除空值所在的行
    大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas日期数据删除的问题,问题如下:大家晚上好,又有问题了,请问下表格中下面空值怎么删除?删不掉。比方说这里我想删HOBBY这一列下面的空值,我是这样子做的df_new.dropna(subset='HOBBY',inplace=True),但空值所......
  • Pandas中如何删除空值所在的行
    大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas日期数据删除的问题,问题如下:大家晚上好,又有问题了,请问下表格中下面空值怎么删除?删不掉。比方说这里我想删HOBBY这一列下面的空值,我是这样子做的df_new.dropna(subset='HOBBY',inplace=True),但空......
  • 大龄程序员应该如何生存?
    都说程序员是吃青春饭的,35岁之后失业就不得不离开这个行业。大部分互联网公司在招聘时会限制年龄35岁以下,裁员时,35岁以上的人员也是重灾区...难道程序员真的就是在35岁该退休了吗?为什么软件开发行业看不见白发苍苍的程序员?大龄程序员都去哪里了?各个公司会辞退大龄程序员吗......
  • 拿到一个需求准备写代码时,如何先正确的画出一个流程图
    制作流程图是将需求可视化并明确步骤的重要工具。以下是一些建议,帮助你正确制作流程图:1.理解需求:在开始绘制流程图之前,确保你充分理解需求。明确输入、输出和主要步骤。2.明确定义起始和结束点:标识流程图的起始和结束点,通常用椭圆或矩形表示。使用标准的流程图符号,如矩......
  • 快乐学Python,如何正确使用pandas处理时间类型的数据?
    在日常的数据分析工作中,常常会有根据日期来对数据进行分析。比如我们需要通过用户的下单时间来分析用户在不同时间段对商品的喜好;如通过访问日志的访问时间来分析系统的访问周期和负载,为不同时间段的资源调配提供依据;如通过用户刷短视频的时间来分析用户的行为特征和工作时间和工种......
  • 软件测试/测试开发/全日制|Pytest allure如何添加测试用例步骤
    前言在编写自动化测试用例的时候经常会遇到需要编写流程性测试用例的场景,一般流程性的测试用例的测试步骤比较多,我们在测试用例中添加详细的步骤会提高测试用例的可阅读性。在allure提供给我们的众多装饰器中,就有一个非常符合我们的需求,它就是allure.step(),它可以帮助我们在测试用......
  • 如何创建自定义启动器
    对于要自定义启动器,我们首先分析下此依赖结构,随后再创建maven项目就拿SpringBoot起步依赖来说。1.首先需要创建一个父工程如名称aliyun-parentd,编写pom.xml文件中的内容(1).修改打包方式为pom(2).继承springboot起步依赖名称是spring-boot-parent-starter2.后面需要创建你所......
  • 如何做好一个信息系统项目经理,一个项目经理的个人体会和经验总结(三)
    前言今天我们继续聊聊在项目开发阶段,项目经理需要做好的事情......
  • 软件测试/测试管理|如何解决团队内的冲突?
    测试管理班是专门面向测试与质量管理人员的一门课程,通过提升从业人员的团队管理、项目管理、绩效管理、沟通管理等方面的能力,使测试管理人员可以更好的带领团队、项目以及公司获得更快的成长。提供1v1私教指导,BAT级别的测试管理大咖量身打造职业规划。在测试管理领域,有效的......
  • 软件测试/测试管理|如何确定一个好的淘汰制度
    测试管理班是专门面向测试与质量管理人员的一门课程,通过提升从业人员的团队管理、项目管理、绩效管理、沟通管理等方面的能力,使测试管理人员可以更好的带领团队、项目以及公司获得更快的成长。提供1v1私教指导,BAT级别的测试管理大咖量身打造职业规划。在测试管理领域,淘汰机......