首页 > 其他分享 >BPF BTF 详解

BPF BTF 详解

时间:2024-03-07 23:45:01浏览次数:14  
标签:__ KIND BPF eBPF BTF u32 详解 define

1. 介绍

BTF(BPF Type Format)是内嵌在BPF(Berkeley Packet Filter)程序中的数据结构描述信息。BPF原本是用于数据包过滤的编程语言,但随着eBPF(extended BPF)的发展,它的用途已经扩展到多种内核子系统中,包括性能监测、网络安全和配置管理等。
BTF是为了实现更复杂的eBPF程序而设计的。其提供了一种机制,通过它可以将编程时使用的数据结构(如C语言中的结构体、联合体、枚举等)的信息嵌入到eBPF程序中。这样做的主要目的是为了让eBPF程序在运行时能够具有类型安全(Type Safety),同时也便于内核和用户空间的程序理解和操作这些数据结构。
在eBPF程序开发过程中,用户通常会在用户空间编写C代码,然后使用特定的编译器(如clang)编译这些代码为eBPF字节码。由于C程序中定义的复杂数据结构信息在编译为eBPF字节码过程中会丢失,因此BTF被设计来保留这些信息。当eBPF程序加载到内核时,BTF信息可以被内核使用,以确保程序操作的数据结构与内核预期的一致,从而保证程序的正确运行。
举个例子,如果eBPF程序需要访问内核数据结构,BTF就能够提供这些内核数据结构的确切布局,让eBPF程序能够安全而准确地读取或修改这些数据。
总之,BTF使得eBPF程序能更安全且方便地与复杂的数据类型互动,并有助于提高eBPF程序与内核间的兼容性和稳定性。

BTF(BPF 类型格式)是一种元数据格式,对与 BPF 程序 /map 有关的调试信息进行编码。BTF 这个名字最初是用来描述数据类型。后来,BTF 被扩展到包括已定义的子程序的函数信息和行信息。

调试信息可用于 map 的更好打印、函数签名等。函数签名能够更好地实现 bpf 程序/函数的内核符号。行信息有助于生成源注释的翻译字节码、JIT 代码和验证器的日志。

BTF 规范包含两个部分:

  • BTF 内核 API
  • BTF ELF 文件格式
    内核 API 是用户空间和内核之间的约定。内核在使用之前使用 BTF 信息对其进行验证。ELF 文件格式是一个用户空间 ELF 文件和 libbpf 加载器之间的约定。

类型和字符串部分(section)是 BTF 内核 API 的一部分,描述了 bpf 程序所引用的调试信息(主要是与类型有关的)。这两个部分将在 BTF_Type_String 章节中详细讨论。

2. BTF 类型和字符串编码

文件 include/uapi/linux/btf.h 提供了关于类型/字符串如何编码的更高层次的定义。

数据块(blob)的开头必须是:

struct btf_header {
    __u16 magic;
    __u8 version;
    __u8 flags;
    __u32 hdr_len;


    /* 所有的偏移量都是相对于这个头的末尾的字节 */
    __u32 type_off; /* 类型部分的偏移量 */
    __u32 type_len; /* 类型部分的长度 */
    __u32 str_off;  /* 字符串部分的偏移量 */
    __u32 str_len;  /* 字符串部分的长度 */
};

magic 数值是 0xeB9F,其在对大、小端系统上的编码有所不同,这可以用来测试 BTF 所在系统是否为大、小端系统。btf_header 被设计为可扩展的,当数据 blob 生成时, hdr_len 等于 sizeof(struct btf_header)。

2.1 字符串编码

字符串部分的第一个字符串必须以 null 结尾字符串。字符串表的其他部分有其他非 null 结尾的字符串连接而成。

2.2 类型编码

类型标识 0 是为 void 类型保留的。类型部分(section)是按顺序解析,每个类型以 ID 从 1 开始的进行编码。目前,支持以下类型:

#define BTF_KIND_INT 1          /* 整数 */
#define BTF_KIND_PTR 2          /* 指针 */
#define BTF_KIND_ARRAY 3        /* 数组 */
#define BTF_KIND_STRUCT 4       /* 结构体 */
#define BTF_KIND_UNION 5        /* 联合体 */
#define BTF_KIND_ENUM 6         /* 枚举 */
#define BTF_KIND_FWD 7          /* 前向引用 */
#define BTF_KIND_TYPEDEF 8      /* 类型定义 */
#define BTF_KIND_VOLATILE 9     /* VOLATILE 变量 */
#define BTF_KIND_CONST 10       /* 常量 */
#define BTF_KIND_RESTRICT 11    /* 限制性 */
#define BTF_KIND_FUNC 12        /* 函数 */
#define BTF_KIND_FUNC_PROTO 13  /* 函数原型 */
#define BTF_KIND_VAR 14         /* 变量 */
#define BTF_KIND_DATASEC 15     /* 数据部分 */

注意,类型部分是对调试信息进行编码的,而不是类型自身。BTF_KIND_FUNC 不是一个类型, 它代表一个已定义的子程序。

每个类型都包含以下常见的数据:

struct btf_type {
    __u32 name_off;
    /* "info" 位值设置如下:
     * 第 0-15 位:vlen(例如结构的成员)
     * bits 16-23: unused
     * bits 24-27: kind (e.g. int, ptr, array...etc)
     * bits 28-30 位:未使用
     * bits 31: kind_flag, 目前被 struct, union 和 fwd 使用
     */
    __u32 info;
    
    /* "size" 被 INT、ENUM、STRUCT  和 UNION 使用
     * "size" 用于描述类型的大小
     *
     * "type“ 被  PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, FUNC 和 FUNC_PROTO 使用。
     * "type" 是指另一个类型的 type_id
     */
    union {
            __u32 size;
            __u32 type;
    };
};

libbpf 库底层使用的结构:

struct btf {
	void *data;
	struct btf_type **types;
	u32 *resolved_ids;
	u32 *resolved_sizes;
	const char *strings;
	void *nohdr_data;
	struct btf_header hdr;
	u32 nr_types;
	u32 types_size;
	u32 data_size;
	refcount_t refcnt;
	u32 id;
	struct rcu_head rcu;
};

对于某些类别来讲,通用数据之后是特定类型的数据。在 struct btf_type 中的 name_off 字段指定了字符串表中的偏移。

标签:__,KIND,BPF,eBPF,BTF,u32,详解,define
From: https://www.cnblogs.com/linhaostudy/p/18060055

相关文章

  • 常用开发板引脚引出详解
    esp32/8266/01s/arduino/(STM32有cubemx,就不重复搞了)esp32-s3 arduinonanoPinout-NANO_latest在Arduino上,ADC具有10位分辨率,这意味着它可以通过1,024个数字电平表示模拟电压。ADC将电压转换成微处理器可以理解的位。ICSP表示在线串行编程。该名称源自在系统编程(ISP)。......
  • React — Redux详解
    Redux是一个用于JavaScript应用程序的状态管理库。它可以帮助您管理应用程序中的状态,并确保状态的一致性和可预测性。Redux主要用于处理大型应用程序中的复杂状态逻辑,例如跨组件共享状态、处理异步数据流等。Redux的核心概念包括:Store(存储):Redux应用程序的状态......
  • 常见中小型企业组网架构详解
    “ 中小型企业内网网络架构是怎么组成的,分几层结构,vlan怎样划分,常用到的动态路由协议,静态路由协议,基本上所有三层二层技术全部会用得到!”网络拓扑这里用Cisco的packettracer教学工具进行搭建演示。整体网络拓扑如下所示。应用到的技术有:OSPF、VLAN、VTP、Channel、HSRP、SVI、......
  • 使用BPF之前和之后生成直方图过程的对比
    以bitehist为例:使用BPF之前:1、在内核中:开启磁盘IO事件的插桩观测。2、在内核中,针对每个事件:向perf缓冲区写入一条记录。如果使用了跟踪点技术(推荐方式),记录中会包含关于磁盘IO的几个元数据字段。3、在用户空间:周期性地将所有事件的缓冲区内容复制到用户空间4。在用户空间:......
  • 多线程系列(十五) -常用并发工具类详解
    一、摘要在前几篇文章中,我们讲到了线程、线程池、BlockingQueue等核心组件,其实JDK给开发者还提供了比synchronized更加高级的线程同步组件,比如CountDownLatch、CyclicBarrier、Semaphore、Exchanger等并发工具类。下面我们一起来了解一下这些常用的并发工具类!二、常用并发......
  • 详解Python魔法函数,__init__,__str__,__del__
    1、简介Python作为一门灵活而强大的编程语言,提供了许多特殊的方法,被称为魔法函数(Magicmethods)。这些魔法函数以双下划线开头和结尾,能够让我们自定义类的行为,使得Python更加灵活和易用。本文将详细介绍Python中的魔法函数,帮助读者理解其作用和用法。1.1、什么是魔法函数?魔法函......
  • CMD命令大全详解
    1、gpedit.msc-----组策略。2.、sndrec32-------录音机。3、Nslookup-------IP地址侦测器,是一个监测网络中DNS服务器是否能正确实现域名解析的命令行工具。它在WindowsNT/2000/XP中均可使用,但在Windows98中却没有集成这一个工具。【cmd命令大全】一、CMD命令4、......
  • nginx rewrite参数详解
    Nginx的rewrite指令用于重写URL,它有几个参数,这些参数定义了如何匹配和重写请求的URL。以下是rewrite指令的常见参数及其说明:Regex:这是一个正则表达式,用于匹配请求的URI。Nginx将使用这个正则表达式来查找与请求URI相匹配的模式。Replacement:这是重写后的URI,可以包含正则表达式......
  • Unity3D 渲染队列 ZTest与ZWrite详解
    在Unity3D中,渲染队列(RenderingQueue)是一个非常重要的概念,它决定了游戏中各个物体的渲染顺序和优先级。而在渲染队列中,ZTest和ZWrite又是两个关键的参数,它们决定了物体在渲染的过程中如何处理深度测试和深度写入。本文将详细介绍Unity3D中的渲染队列、ZTest和ZWrite的概念,并给出相......
  • Unity3D 立方体纹理与自制天空盒详解
    在Unity3D中,立方体纹理和自制天空盒是常见的技术,它们可以帮助开发者创建出更加真实和引人入胜的游戏场景。本文将详细介绍Unity3D中立方体纹理和自制天空盒的实现方法,希望能帮助读者更好地理解和运用这些技术。对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小......