eBPF 虚拟机是如何工作的

简介: 【2月更文挑战第3天】

eBPF 是一个运行在内核中的虚拟机,很多人在初次接触它时,会把它跟系统虚拟化(比如 kvm)中的虚拟机弄混。其实,虽然都被称为“虚拟机”,系统虚拟化和 eBPF 虚拟机还是有着本质不同的。


系统虚拟化基于 x86 或 arm64 等通用指令集,这些指令集足以完成完整计算机的所有功能。而为了确保在内核中安全地执行,eBPF 只提供了非常有限的指令集。这些指令集可用于完成一部分内核的功能,但却远不足以模拟完整的计算机。为了更高效地与内核进行交互,eBPF 指令还有意采用了 C 调用约定,其提供的辅助函数可以在 C 语言中直接调用,极大地方便了 eBPF 程序的开发。


eBPF 在内核中的运行时主要由  5  个模块组成:

image.png

  • 第一个模块是  eBPF 辅助函数。它提供了一系列用于 eBPF 程序与内核其他模块进行交互的函数。这些函数并不是任意一个 eBPF 程序都可以调用的,具体可用的函数集由 BPF 程序类型决定。
  • 第二个模块是  eBPF 验证器。它用于确保 eBPF 程序的安全。验证器会将待执行的指令创建为一个有向无环图(DAG),确保程序中不包含不可达指令;接着再模拟指令的执行过程,确保不会执行无效指令。
  • 第三个模块是由  11 个 64 位寄存器、一个程序计数器和一个 512 字节的栈组成的存储模块。这个模块用于控制 eBPF 程序的执行。其中,R0 寄存器用于存储函数调用和 eBPF 程序的返回值,这意味着函数调用最多只能有一个返回值;R1-R5 寄存器用于函数调用的参数,因此函数调用的参数最多不能超过 5 个;而 R10 则是一个只读寄存器,用于从栈中读取数据。
  • 第四个模块是即时编译器,它将 eBPF 字节码编译成本地机器指令,以便更高效地在内核中执行。
  • 第五个模块是  BPF 映射(map),它用于提供大块的存储。这些存储可被用户空间程序用来进行访问,进而控制 eBPF 程序的运行状态。


eBPF 程序是什么时候执行的,查看到 BCC 的执行过程,首先,打开一个终端,执行下面的命令:

# -ebpf表示只跟踪bpf系统调用
sudo strace -v -f -ebpf ./hello.py

稍等一会,会看到如下的输出:

bpf(BPF_PROG_LOAD,
    {
        prog_type=BPF_PROG_TYPE_KPROBE,
        insn_cnt=13,
        insns=[
            {code=BPF_ALU64|BPF_K|BPF_MOV, dst_reg=BPF_REG_1, src_reg=BPF_REG_0, off=0, imm=0x21},
            {code=BPF_STX|BPF_H|BPF_MEM, dst_reg=BPF_REG_10, src_reg=BPF_REG_1, off=-4, imm=0},
            {code=BPF_ALU64|BPF_K|BPF_MOV, dst_reg=BPF_REG_1, src_reg=BPF_REG_0, off=0, imm=0x646c726f},
            {code=BPF_STX|BPF_W|BPF_MEM, dst_reg=BPF_REG_10, src_reg=BPF_REG_1, off=-8, imm=0},
            {code=BPF_LD|BPF_DW|BPF_IMM, dst_reg=BPF_REG_1, src_reg=BPF_REG_0, off=0, imm=0x6c6c6548},
            {code=BPF_LD|BPF_W|BPF_IMM, dst_reg=BPF_REG_0, src_reg=BPF_REG_0, off=0, imm=0x57202c6f},
            {code=BPF_STX|BPF_DW|BPF_MEM, dst_reg=BPF_REG_10, src_reg=BPF_REG_1, off=-16, imm=0},
            {code=BPF_ALU64|BPF_X|BPF_MOV, dst_reg=BPF_REG_1, src_reg=BPF_REG_10, off=0, imm=0},
            {code=BPF_ALU64|BPF_K|BPF_ADD, dst_reg=BPF_REG_1, src_reg=BPF_REG_0, off=0, imm=0xfffffff0},
            {code=BPF_ALU64|BPF_K|BPF_MOV, dst_reg=BPF_REG_2, src_reg=BPF_REG_0, off=0, imm=0xe},
            {code=BPF_JMP|BPF_K|BPF_CALL, dst_reg=BPF_REG_0, src_reg=BPF_REG_0, off=0, imm=0x6},
            {code=BPF_ALU64|BPF_K|BPF_MOV, dst_reg=BPF_REG_0, src_reg=BPF_REG_0, off=0, imm=0},
            {code=BPF_JMP|BPF_K|BPF_EXIT, dst_reg=BPF_REG_0, src_reg=BPF_REG_0, off=0, imm=0}
        ],
        prog_name="hello_world",
        ...
    },
    128) = 4

这些参数看起来很复杂,但实际上,如果查询  bpf 系统调用的格式(执行  man bpf 命令),就可以发现,它实际上只需要三个参数:

int bpf(int cmd, union bpf_attr *attr, unsigned int size);


对应前面的 strace 输出结果,这三个参数的具体含义如下。


第一个参数是  BPF_PROG_LOAD , 表示加载 BPF 程序。


第二个参数是  bpf_attr  类型的结构体,表示 BPF 程序的属性。其中,有几个需要你留意的参数,比如:

  • prog_type  表示 BPF 程序的类型,这儿是  BPF_PROG_TYPE_KPROBE ,跟我们 Python 代码中的  attach_kprobe  一致;
  • insn_cnt  (instructions count) 表示指令条数;
  • insns  (instructions) 包含了具体的每一条指令,这儿的 13 条指令跟我们前面  bpftool prog dump  的结果是一致的;
  • prog_name  则表示 BPF 程序的名字,即  hello_world 。


第三个参数 128 表示属性的大小。

相关文章
|
Linux BI 网络架构
mtr网络监测工具
mtr网络监测工具
1959 2
mtr网络监测工具
|
网络协议 应用服务中间件 网络安全
|
索引 存储 数据库
数据库设计规范
基于阿里数据库设计规范扩展而来
51705 4
|
4月前
|
Web App开发 人工智能 运维
怎么让Gemini操作Chrome浏览器,真相让老金无语。。。
接前两天的Gemini in Chrome文章。 Chrome现在内置了Gemini。 能当浏览器助手。 帮你整理网页信息。 还能用Nano Banana画图。
|
4月前
|
存储 弹性计算 缓存
阿里云服务器最便宜多少钱?轻量应用服务器38元,云服务器99元(附购买教程)
阿里云服务器受用户青睐,价格降低后更具吸引力,其中轻量应用服务器仅需38元/年,云服务器最低99元/年。38元轻量服务器配置为2核2G,适合个人建站;99元云服务器为经济型e实例,2核2G配置,适合个人开发者、初创企业、小型网站等;另有199元/年的通用算力型u1实例,适合中小型企业网站、中型Web应用等。用户可根据需求在阿里云活动页面选择并购买,享受稳定可靠的云服务。
|
负载均衡 Kubernetes 网络协议
如何在集群的负载均衡过程保留请求源IP
本文探讨了在Kubernetes (k8s)集群中如何确保服务获取到请求的源IP。通常,源IP可能会因网络地址转换(NAT)和代理服务器而丢失。为保留源IP,文章建议在代理服务器层添加HTTP头`X-REAL-IP`字段。在K8s中,通过设置`externalTrafficPolicy: Local`可保留源IP,但这会牺牲负载均衡。使用Ingress时,可通过配置Ingress Controller的`use-forwarded-headers`并调整ConfigMap来同时保留源IP和实现负载均衡。文章适用于对网络和K8s感兴趣的读者。
614 3
|
Rust Linux iOS开发
Rust 交叉编译 macOS 为 Linux 和 Windows
Rust 交叉编译 macOS 为 Linux 和 Windows
855 0
|
存储 SQL 关系型数据库
MySQL的参数optimizer_switch
`optimizer_switch`是MySQL系统变量,用于控制查询优化器行为。它由键值对组成,如`index_merge=on/off`,用于开启或关闭特定优化功能。要查看当前设置,运行`SHOW VARIABLES LIKE 'optimizer_switch';`,修改则用`SET`命令,如`SET optimizer_switch='index_merge=off';`。
757 1
|
网络协议 网络架构 Windows
NDP 常用报文格式
【2月更文挑战第27天】
|
域名解析 缓存 网络协议

热门文章

最新文章