ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

eBPF学习笔记(一)概述

2022-05-26 15:31:39  阅读:267  来源: 互联网

标签:字节 eBPF BPF 程序 笔记 概述 内核 加载


eBPF技术简述
       eBPF 是起源于内核的革命性技术,从 2011 年开发至今,eBPF 社区依然非常活跃 。eBPF 可以通过热加载的sandbox程序到内核中而不需要insmod module的方式,避免内核模块的方式可能会引入宕机风险,并具备堪比原生代码的执行效率。eBPF程序不会引起系统宕机,Just-In-Time (JIT) compiler编译器假设代码是安全但有 verification engine从汇编语言级别检查程序的有效性,程序中规定了内存范围、有限的循环、bpf_spin_lock()不会死锁、不可以在free之后使用、不可以有内存泄露等。
使用eBPF技术可以应用在很多场景中:

  • 在现代数据中心和云原生环境中提供高性能的网络和负载平衡
  • 以低开销提取细粒度的安全可观察数据,帮助应用程序开发人员跟踪应用程序,提供性能故障排除、应用程序和容器运行时安全实施的见解

等等,可能性是无限的。

 eBPF架构图

图1 简易的eBPF程序架构图

图1是一个简易的eBPF程序架构图,它描述了一个eBPF程序的主要构成部分和程序编译、运行顺序。先来看一个eBPF程序的主要构成部分:

1. 用户空间的BPF字节码:图1中用户空间绿色的部分,用户空间的BPF程序,文件名一般是xxx.bpf.c,由该文件生成BPF字节码

2. 用户空间的程序代码:图1中用户空间紫色的部分,表述从内核获取数据后的处理逻辑。当程序挂载的系统调用被触发,就会把相应的事件数据传输到perf_event data中,由用户空间的代码来分析行为。

3. 内核空间的verifier: 验证器确保了eBPF程序可以安全运行。它验证程序是否满足几个条件,例如:

  • 加载eBPF程序的流程拥有所需的功能(特权)
  • 程序不会崩溃或以其他方式损害系统
  • 程序不能使用任何未初始化的变量或越界访问内存
  • 程序必须符合系统的尺寸要求,不可能加载任意大的eBPF程序
  • 程序必须具有有限的复杂性。验证者将评估所有可能的执行路径,并且必须能够在配置的复杂度上限范围内完成分析
  • 程序总是运行到结束,即没有死循环

4. 内核空间的JIT Compiler:即时(JIT)编译步骤将程序的通用字节码转换为特定于机器的指令集,以优化程序的执行速度。这使得eBPF程序可以像本地编译的内核代码或作为内核模块加载的代码一样高效地运行。

5. 内核空间的BPF沙箱程序:这是整个程序的核心部分,BPF程序可以被挂载到多种系统点:kprobe、uprobe、tracepoint和perf_events. 至于你关注的系统调用属于那种系统hook点,可以用 bpftrace -l 命令来查询。当程序挂载的系统调用被触发,就会把相应的事件数据传输到perf_event data中.

6. 内核空间的MAPS:eBPF非常重要的能力是能分享收集到的信息并存储状态。为了达到这个目的,eBPF使用maps来存储数据。这些数据可以是各种各样的struct. Maps中的数据可以被用户空间的程序通过系统调用读取。

 然后再来看一个eBPF程序的主要流程: 

1. 编写BPF代码,生成字节码

2. 加载BPF字节码到内核上

3. 异步读取maps数据

4. 系统事件触发,用户空间接收到事件信息开始处理分析逻辑

 eBPF开发工具链

eBPF程序开发常使用的方法分为bcc、bpftrace、eBPF Go Library和libbpf. 

  • BCC:BCC是一个框架,该框架使得用户可以写python程序来和eBPF内核函数交互,这些python程序内嵌了eBPF程序。运行python程序就可以生成eBPF字节码并把它们加载到内核。
  • bpftrace:bpftrace是一种用于Linux eBPF的高级跟踪语音,在4.x及以上的内核中可用。bpftrace使用LLVM作为后端来编译脚本成eBPF字节码并使用BCC来和Linux eBPF子系统进行交互。bpftrace语言的灵感来自awk、C以及DTrace和SystemTap等早期跟踪程序。
  • eBPF Go Library:eBPF Go库提供了一个通用的eBPF库,它将获取eBPF字节码的过程与eBPF程序的加载和管理分离开来。eBPF程序通常是通过编写高级语言创建的,然后使用clang/LLVM编译器编译成eBPF字节码。
  • libbpf Library:libbpf 库是基于 C/C++ 的通用 eBPF 库,可以帮助把从clang/LLVM编译器生成的eBPF对象文件的加载解耦到内核,它通过为应用程序提供易于使用的API库来抽象化和BPF系统调用的交互操作。例如开源项目tracee就是使用的libbpf进行开发的,它使用的libbpfgo其实是对libbpf用go语言进行的封装。

 以上四种方法只是书写eBPF程序和生成eBPF字节码的方式不同,也就是图1的第一个步骤不同,其他的都是一致的。

 

标签:字节,eBPF,BPF,程序,笔记,概述,内核,加载
来源: https://www.cnblogs.com/janeysj/p/16185097.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有