1. eBPF 子系统

144 阅读4分钟
  1. eBPF 子系统是什么?

      eBPF 子系统是 Linux 内核的一个核心功能模块。

    • 内核组成部分:它以代码的形式嵌入在内核源码中,作为 Linux 内核编译和运行时的一部分。
    • 功能模块:提供一种机制,使得用户可以动态扩展内核功能,而无需重新编译或加载模块。
    • 运行环境:eBPF 子系统随着内核启动加载,并始终作为内核的一部分运行。

      关键特点

    • 嵌入式:eBPF 是内核的原生能力,而非独立运行的服务或进程。
    • 动态扩展:通过用户加载 eBPF 程序,eBPF 子系统支持对内核行为进行定制。
    • 安全可靠:运行 eBPF 程序时会经过严格的验证,确保不会影响内核稳定性。

  1. eBPF 子系统的存活方式

      eBPF 子系统在编译、启动和运行时的生存状态如下:

      2.1 作为内核的一部分

        编译阶段

    • eBPF 子系统的代码主要位于 kernel/bpf/ 和相关子模块中。
    • 当编译 Linux 内核时,eBPF 子系统代码被编译为内核镜像(如 vmlinuz)。
    • 如果内核编译选项中启用了 eBPF 功能(现代内核默认启用),相关功能模块会被内核构建。

        启动阶段

    • 当 Linux 系统启动时,eBPF 子系统会被初始化:

      • 加载 eBPF 核心组件(如虚拟机、验证器、JIT 编译器等)。
      • 注册系统调用接口 bpf(),允许用户通过接口与子系统交互。
      • 初始化 eBPF Maps 支持,用于数据存储和共享。
    • 这一过程由内核代码自动完成,无需用户干预。

        运行时:- eBPF 子系统与内核紧密耦合,作为内核态的功能模块运行。

    • 它始终驻留在内存中,等待用户加载 eBPF 程序。
    • 用户可以通过工具(如 bpftool)或 bpf() 系统调用向内核加载 eBPF 程序。

      2.2 为什么 eBPF 子系统不是进程?- 内核态模块

    -   eBPF 子系统运行在内核空间中,与调度器、网络栈等模块类似。
    -   它不会以用户空间进程的形式存在,而是内核功能的一部分。
    
    • 共享内核 地址空间

      • 作为内核代码的一部分,eBPF 子系统与其他模块共享内核内存。
      • 这种设计避免了用户态与内核态之间的上下文切换,性能更高效。
    • 始终驻留内核

      • 只要内核在运行,eBPF 子系统就会存在,随时响应用户请求。

  1. eBPF 子系统的存在状态

      eBPF 子系统的核心组件包括:

    1. eBPF ****虚拟机

      1. 提供执行环境,解释和运行 eBPF 字节码。
    2. Verifier(验证器)

      1. 在加载 eBPF 程序时,验证代码的安全性和合法性。
    3. JIT 编译器

      1. 将 eBPF 字节码翻译为本地机器代码,提高运行效率。
    4. 挂载点

      1. 支持 eBPF 程序挂载到特定内核事件(如 Kprobe、Tracepoint)。
    5. BPF Maps 支持

      1. 提供内核态与用户态之间的数据存储和交换机制。

  1. eBPF 子系统的运行过程

      系统启动后的状态:- eBPF 子系统已经初始化,但不会主动运行。

    • bpf() 系统调用接口已准备好,用户可加载程序。

      加载 eBPF 程序后的状态:- 用户通过工具或 API 加载 eBPF 程序。

    • eBPF 子系统接收请求,验证并加载程序。
    • 程序被挂载到某个事件触发点(如网络包处理或内核跟踪点)。
    • 一旦触发事件,eBPF 程序会动态运行。

  1. eBPF 子系统的“存活”总结

    1. 内核启动时加载

      1. eBPF 子系统随着 Linux 内核一起加载,无需用户额外操作。
    2. 作为内核功能存在

      1. 它是内核功能模块,不是用户态的独立进程。
    3. 按需运行

      1. 没有加载 eBPF 程序时,子系统是静态存在的,不消耗额外资源。
      2. 加载 eBPF 程序后,它会动态激活,根据触发条件执行。
    4. 始终驻留内核

      1. 只要内核运行,eBPF 子系统就处于“随时待命”状态。

  1. 示例:eBPF 子系统的行为

      初始状态

    • 系统启动后,eBPF 子系统完成初始化:

      • 虚拟机、验证器、JIT 编译器已加载,但未运行任何程序。
      • bpf() 系统调用已注册,但尚未被调用。

      动态加载程序后

    • 用户通过工具加载一个 eBPF 程序(如 bpf_prog_load())。

    • eBPF 子系统:

      • 验证程序合法性。
      • 将程序挂载到指定的触发点(如网络路径)。
      • 触发事件时执行该程序。

  1. 类比总结

      eBPF 子系统可以类比为一个工厂的自动化区域:

    • 工厂:Linux 内核。
    • eBPF 子系统:工厂中的一个专门功能区域,默认处于待机状态。
    • eBPF 程序:用户提交的任务,只有需要时才激活功能区域。

      这种设计使得 eBPF 子系统高效且灵活,能够随时响应用户需求,同时最大化系统资源利用率。