热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

eBPF1基础与技术储备

文章目录一、背景与基础1.1基础之基础1.gcc、llvm、clang等是什么?2..elf对象文件处于程序编译的什么阶段?1.2BPF基础和技术储备1


文章目录

  • 一、背景与基础
    • 1.1 基础之基础
      • 1. `gcc、llvm、clang`等是什么?
      • 2. `.elf`对象文件处于程序编译的什么阶段?
    • 1.2 `BPF`基础和技术储备
      • 1. 网络监控工具发展历程?发展原因?
      • 2. BPF是什么?eBPF是什么?
      • 3. eBPF做了哪些提升?
      • 4. eBPF感知代码流程?能够使用eBPF做什么?
      • 5. eBPF如何保证安全性?(内核验证器)
      • 6. eBPF虚拟机的内部架构是什么?
      • 7. eBPF的执行流程是什么?
      • 8. eBPF的插桩类型有哪些?
        • 动态插桩:kprobes && uprobes
        • 静态插桩:tracepoint && USDT
      • 9. 如何理解eBPF中的Map?
      • 10. eBPF程序的限制有哪些?
      • 11. eBPF程序编写的组件层次是什么样的?相关工具的实现程度?
      • 12. 工具集`llvm`、`BCC`、`bpftrace`、`IOVisor`层次架构与比较
      • 13. `BPF`运行时模块组成?
    • 1.3 `eBPF`可观测性方向基础
      • 1.`eBPF`可观测性的术语
      • 2. 基础库`libbcc`、`libbpf`的理解?
      • 3. `eBPF`与传统的性能分析工具的不同点?
      • 4. 调用栈回溯(`stack-trace`)
        • 1. 函数调用栈作用?
        • 2. 基于帧指针的栈回溯原理


参考资料:

  • https://davidlovezoe.club/wordpress/archives/1122#BPF%E7%A4%BE%E5%8C%BA%E5%92%8C%E7%94%9F%E6%80%81
  • 《A thorough introduction to eBPF》
  • https://davidlovezoe.club/wordpress/archives/874
  • https://davidlovezoe.club/wordpress/archives/988
  • 极客时间《eBPF核心技术与实战》
  • https://zhuanlan.zhihu.com/p/44922656
  • https://www.ebpf.top/post/ebpf-overview-part-3/
  • 《BPF之巅-洞悉linux系统和应用性能》

一、背景与基础


1.1 基础之基础

在学习eBPF基础之前的基础


1. gcc、llvm、clang等是什么?

编译器分为三个:


  • 前端frontEnd :词法和语法分析,将源代码转换为抽象语法树
  • 优化器Optimizer: 在前端的基础上,对中间代码进行优化
  • 后端backEnd:将优化后的中间代码转化为各自平台的机器码

GCC、llvm、clang


  • GCC: GNU Compiler Collection,GNU编译器套装,是一套由 GNU 开发的编程语言编译器,最先支持C语言,后来演进可处理 C++、Fortran、Pascal、Objective-C、Java等语言

  • llvm:Low Level Virtual Machine, 可用作多种编译器的后端使用(能够让程序语言的编译器优化、链接优化等),支持任何编程语言的静态和动态编译,可以使用它编写自己的编译器

    LLVM的命名最早源自于底层虚拟机(Low Level Virtual Machine)的首字母缩写,由于这个项目的范围并不局限于创建一个虚拟机,这个缩写导致了广泛的疑惑。LLVM开始成长之后,成为众多编译工具及低端工具技术的统称,使得这个名字变得更不贴切,开发者因而决定放弃这个缩写的意涵,现今LLVM已单纯成为一个品牌,适用于LLVM下的所有项目

  • clang:clangllvm的前端,可以用来编译c、c++、ObjectiveC等语言,其以llvm作为后端支持,高效易用,并且与IDE有很好的结合


2. .elf对象文件处于程序编译的什么阶段?

可执行与可链接格式 (英语:Executable and Linkable Format,缩写 ELF,此前的写法是 Extensible Linking Format),常被称为 ELF格式,在计算中,是一种用于可执行文件、目标代码、共享库和核心转储(core dump)的标准文件格式。


  • 编译:

    高级语言 -> 汇编语言 -> 机器语言 : 高级语言最终变为机器语言这样的过程可以统称为编译,具体的方法基本有两种:编译型和解释型

    据此也可分为两大类:一种是编译型语言,例如C,C++,Java,另一种是解释型语言,例如Python、Ruby、MATLAB 、Javascript

  • 四个步骤:

    • 预处理(Preprocessing)

    • 编译(Compilation)

    • 汇编(Assembly)

    • 链接(Linking)

.so文件:动态链接库,也称为共享库, 不能直接运行


1.2 BPF基础和技术储备


1. 网络监控工具发展历程?发展原因?


  • 监控内容:监控内核空间运行的数据(数据包), 抓取和过滤符合特定规则的网络包

  • 发展历程:

    image-20220517110503597

  • 发展原因:

    • 1->2:
      • 效率问题:用户态进程处理监控数据包需要将内核态大量数据包拷贝到用户进程地址空间从而进行分析,设计用户态内核态模式切换(上下文切换),无法处理现在日益增长的数据量(音频、流媒体数据)需求,急迫的需要一个在内核内部运行用户提供的程序的能力
    • 2->3:
      • 原始BPF的设计:设计较差,难以适配新的硬件环境更新。例如:BPF专注于提供少量的RISC指令的特点,因为当前64位寄存器以及多核处理器新指令的的出现,已不再与现代处理器的实际情况相匹配
      • 不仅仅满足于内核数据包的监控,而将功能拓展到例如:性能分析、系统追踪、网络优化等多种类型的工具和平台

Brendan Gregg,他在2017年的linux.conf.au大会上的演讲提到「内核虚拟机eBPF」,表示,“超能力终于来到了Linux操作系统“

因此,Alexei Starovoitov为了更好地利用的现代硬件,提出了扩展型BPF(eBPF)设计。eBPF虚拟机更类似于现代的处理器,允许eBPF指令映射到更贴近硬件的ISA以获得更好的性能


详细完整的历程:

img


2. BPF是什么?eBPF是什么?


  • BPF

Berkeley Packet Filter 伯克利包过滤器,在伯克利大学诞生,为BSD操作系统而开发,后来一直沿用

原始的BPF是设计用来抓取和过滤符合特定规则的网络包, 过滤器是通过程序实现的(用户定义过滤器表达式),并在基于寄存器的虚拟机上运行,使得包过滤直接在内核中执行,避免向用户态复制

image-20220521175501426

基本原理是BPF提供了一种在内核事件和用户程序事件发生时,安全注入代码的机制(运行一小段程序的机制), 这样就让非内核开发人员也可以对内核进行监控和控制


著名的tcpdump就是基于此实现:



  • eBPF

extend Berkeley Packet Filter 拓展BPF, 它演进成为了一套通用执行引擎

BPF的功能升级版,Alexei Starovoitov为了更好地利用的现代硬件,提出了扩展型BPF(eBPF)设计

eBPF的基本架构在于:借助即时编译器JIT,在内核中运行了一个执行引擎(因为编译后直接在cpu上运行,所以相比虚拟机可能执行引擎更为合适),被验证安全的eBPF指令最终都会被内核执行


  • 老版本的Berkeley Packet Filter目前称为cBPF: classic BPF,目前基本废弃,新的Linux内核只运行eBPF, 内核会将cBPF透明的转换为eBPF
  • 特别的,当前cBPFeBPF都统称为BPF了,或者说提到BPF不做特殊说明就是eBPF,BPF应该看作是一个技术名词而不是单纯的缩写(或者说包过滤器了)


  • 二者比较

    image-20220521180300520


3. eBPF做了哪些提升?


  • 速度更快

    • 更贴近硬件的指令集架构ISA,特别是适应64位寄存器以及提升使用的寄存器数量(从2个提升到10个),这样有助于即时编译提高性能;此外eBPF的指令仍然运行在内核中, 不需要向用户态复制数据(也是BPF拥有的),提高了事件处理效率。

      对于某些网络过滤器微基准测试上显示,eBPFx86-64架构上的速度比旧的经典BPF (cBPF)实现最高快四倍,大多数都在1.5倍

  • 支持使用一些受限的系统调用

    • 新的BPF_CALL指令,可以更廉价地调用内核函数
  • 拓展性

    • 功能从包过滤拓展到更多(跟踪过滤、链路追踪、可观测)

      2014年的daedfb22451d这次代码提交中,eBPF虚拟机直接暴露给了用户空间来调用(或者说运行用户空间代码)


4. eBPF感知代码流程?能够使用eBPF做什么?

eBPF怎样感知代码?


  • 将代码放在eBPF的指定的代码路径中,当代码路径被遍历到时,任何附加的eBPF代码都会被执行

能够做什么?


  • 网络数据包/流量的过滤转发

    通过编写程序实现对网络数据包/流量的过滤分发,甚至是修改socket的设置

    实例:

    • XDP这个项目就是专门使用eBPF来执行高性能数据包处理,方法是在收到数据包之后,立即在网络栈的最低层执行eBPF程式
    • seccomp BPF实现了限制一个进程的系统调用方法的使用
  • 调试内核/性能分析

    程序可以添加跟踪点、kprobesperf事件; 对于实时运行的系统,可以不重新编译内核而实现编写和测试新的调试代码

    甚至可以使用eBPF通过「用户空间静态定义的跟踪点」来调试用户空间程序


5. eBPF如何保证安全性?(内核验证器)

如果允许用户空间代码在内核中运行,eBPF如何保证安全性?


  • eBPF分为两个阶段的检查:
    • 第一阶段:加载每个eBPF程序之前
      • 禁止内核锁定:确保eBPF终止时不包含任何可能导致内核锁定的循环逻辑(就是不能有循环),通过程序控制流图CFG来实现
      • 禁止不可达指令:任何有不可达指令的程序都无法加载
    • 第二阶段:模拟执行
      • 禁止越界跳转和越界数据访问:验证器模拟执行eBPF程序,每执行完一次指令就在指令执行之前和之后检查虚拟机的状态,确保寄存器和堆栈状态的有效性,禁止越界跳转和越界数据访问
  • 检查时的优化:裁剪
    • eBPF验证器会智能的检测出已经检查过程序的子集,从而裁剪分支跳过模拟验证的过程
  • 禁止指针运算的安全模式
    • 时机:当没有使用CAP_SYS_ADMIN特权加载eBPF程序的时候就会进入安全模式,安全模式下会确保内核地址不会泄露给没有特权的用户,并且指针不能写入到内存
    • 如果未启用安全模式,则必须在通过检查之后才允许指针运算(检查计算后的指针是否出现类型、位置、边界违反情况等)
  • 无法读取未被初始化(从未被写入内容)的寄存器
    • 寄存器R0-R5的内容在函数调用时会被标记为不可读
    • 对读取栈上的变量也进行了类似的检查,以确保没有指令写入只读类型的帧指针寄存器
  • 最后,验证器使用**eBPF程序类型**(后面将介绍)来限制可以从eBPF程序调用哪些内核函数以及可以访问哪些数据结构

6. eBPF虚拟机的内部架构是什么?

BPF虚拟机的内部架构

image-20220521192823981


7. eBPF的执行流程是什么?

下面就是整个eBPF程序的工作流程图:

img

或者是这张图:

image-20220521142259971

整体的流程可以总结为:


  1. 通过llvm将程序编译为eBPF字节码
  2. 通过bpf系统调用交给内核(也叫load加载)
  3. 内核在接受字节码之前会进行检查检验
  4. 检验通过的字节码提交到即时编译器中运行

8. eBPF的插桩类型有哪些?

插桩是什么?


  • 也就是对某个函数进行埋点为了跟踪系统某些事件的发生

具体的事件源:

image-20220522155105084

具体类型?


动态插桩:kprobes && uprobes

动态插桩:对正在运行的软件插入观测点的能力;如果软件未启动,那么动态插桩的开销为0;具体插桩的位置可以是软件栈中所有函数中任一个

debugger调试器的区别?


  • 调试器是在任意指令地址插入断点的技术,动态插桩则是在软件记录完信息后自动继续执行,不会把控制权交给调试器(无侵入?)

动态插桩有两种探针:


  • 内核态插桩kprobes

    • 可以对任意内核函数进行插桩,还可以对内部指令进行插桩,可以在实时生产环境中使用无需重启系统或内核

    • kretprobes: 对内核函数返回时进行插桩以获取返回值;两者配合可以用来计算函数执行时间

    • 上层追踪器/前端的使用

      • BCC : attach_kprobe()attach_kretprobe()
      • bpftrace: kprobekretprobe探针类型
      • 注:BCCkprobe支持函数开始以及某一偏移量放置探针,而bpftrace只支持函数开始位置插桩
  • 用户态插桩uprobes

    • 几乎类似于kprobes,但是是对用户态程序
    • 上层追踪器/前端的使用
      • BCC : attach_uprobe()attach_uretprobe()
      • bpftrace: uprobeuretprobe探针类型
      • 注:BCCuprobe支持函数开始以及某一偏移量放置探针,而bpftrace只支持函数开始位置插桩


缺点:


  • 注意:虽然插桩性能消耗很小(已做了优化), 但是超高频事件(百万级别)插桩后还是会影响性能,所以建议插桩低频函数或者在测试环境下插桩高频函数
  • 可能随着软件的更新,被插桩的函数也可能会被重新命名或移除(并且在旧版插桩使用的时候可能没有任何输出提示),要重新进行适配
  • 编译器的内联优化,将函数内联处理导致被插桩函数无法被插桩

静态插桩:tracepoint && USDT

为了解决动态插桩的问题,出现了静态插桩,静态插桩会将稳定的事件名字编码到软件代码中,由开发者维护

具体有两种:


  • tracepoint(内核跟踪点)

    • 用来对内核进行静态插桩,内核开发者在某些位置特定放了插桩点,最终会被编译到内核的二进制文件中,用于跟踪
    • 如果有内核跟踪点可以满足需求,优先使用它而不是kprobes, 因为前者更加稳定
    • 跟踪点一般格式&#xff1a;<子系统>:<事件名>
    • 上层追踪器/前端的使用
      • BCC : TRACEPOINT_PROBE()
      • bpftrace&#xff1a;跟踪点探针类型
    • 原始跟踪点BPF_RAW_TRACEPOINT: 避免一些没必要的参数传递&#xff0c;提高性能 (比kprobes稳定&#xff0c;因为其探针函数名是稳定的&#xff0c;参数可能是不稳定的)
  • USDT(用户态静态定义跟踪插桩技术 user-level statically defined tracing)

    • 用户空间版的跟踪点机制

    • 依赖于外部系统跟踪器唤起&#xff0c;如果没有&#xff0c;应用中的USDT也不会做任何事 (不用担心写在源代码中的探针会带来性能开销&#xff0c;如果外部没启用&#xff0c;那么该代码会被直接跳过)

    • 上层追踪器/前端的使用

      • BCC : USDT().enable_probe()
      • bpftrace&#xff1a;USDT探针类型
    • 动态USDT:

      • 对于编译型语言在静态USDT直接编译到二进制文件中&#xff0c;而对于动态编译型语言(运行时编译&#xff0c;例如java/jvm)&#xff0c;动态USDT就起作用了
      • JVM 已经内置在C&#43;&#43;代码库中许多动态USDT探针, 包括GC、类加载等&#xff1b;但是java这种依靠JIT即时编译的方式难以使用动态USDT&#xff08;因为动态USDT是一个动态链接库&#xff0c;需要提前编译好、带一个包含了探针描述的notesELF文件&#xff09;

缺点&#xff1a;增加维护成本&#xff0c;数量一般较少


动态插桩、静态插桩的基本原理将在后续介绍



9. 如何理解eBPF中的Map?

map又称为映射&#xff0c;BPF程序可以利用其进行存储

核心职责&#xff1a;存储eBPF运行时状态即用户程序与运行在内核的eBPF程序交互载体

运行在内核的eBPF程序收集目标状态存储在map中&#xff0c;随后用户程序再从映射中读取这些状态


10. eBPF程序的限制有哪些&#xff1f;

保证安全性就意味着限制&#xff0c;所以eBPF并不是万能的

具体的限制包括&#xff1a;


  • 校验限制&#xff1a;必须通过校验才可以执行&#xff0c;并且不能包含不可到达的指令
  • 内核函数限制&#xff1a;内核函数只可以调用API定义的辅助函数
  • 存储限制&#xff1a;eBPF程序栈最大只有512字节&#xff0c;需要更大的存储要借助映射存储
  • 指令数量限制&#xff1a;内核5.2之前支持4096条指令&#xff0c;之后支持100万条
  • 移植性/适配性&#xff1a;不同内核版本下的移植可能需要修改源码并重新编译

具体内核版本要求和函数功能支持见&#xff1a;https://github.com/iovisor/bcc/blob/master/docs/kernel-versions.md


11. eBPF程序编写的组件层次是什么样的&#xff1f;相关工具的实现程度&#xff1f;

eBPF程序编写的整体的组织架构&#xff1a;


  • 后端&#xff1a;这是在内核中加载和运行的 eBPF 字节码。它将数据写入内核 map 和环形缓冲区的数据结构中。
  • 加载器&#xff1a;它将字节码后端加载到内核中。通常情况下&#xff0c;当加载器进程终止时&#xff0c;字节码会被内核自动卸载。
  • 前端&#xff1a;从数据结构中读取数据&#xff08;由之前的后端写入&#xff09;并将其显示给用户。
  • 数据结构&#xff1a;这些是后端前端之间的通信手段。它们是由内核管理的 map 和环形缓冲区&#xff0c;可以通过文件描述符访问&#xff0c;并需要在后端被加载之前创建。它们会持续存在&#xff0c;直到没有更多的后端前端进行读写操作

eBPF 程序可以更加复杂&#xff1a;多个后端可以由一个&#xff08;或单独的多个&#xff09;加载器进程加载&#xff0c;写入多个数据结构&#xff0c;然后由多个前端进程读取&#xff0c;所有这些都可以发生在一个跨越多个进程的用户 eBPF 应用程序中。

img


12. 工具集llvmBCCbpftraceIOVisor层次架构与比较

与之相关的知名工具包括&#xff1a;


  • 层级一&#xff1a;llvm

    一个编译器&#xff0c;帮助高级语言(c、GO、Rust)的子集被编译成为eBPF字节码程序&#xff1b;将“”受限的C语言“”(符合eBPF验证规范的)编译为ELF对象文件&#xff0c;随后即可通过bpf等系统调用实现加载到内核中&#xff1b;受限的c语言的引入带来的好处是更加容易用高级语言编写&#xff0c;带来的坏处在于加载器程序的复杂性变高(需要解析ELF对象)

  • 层级二&#xff1a;BCC

    一个BPF工具链集合&#xff08;libbcc、libbpf的前身&#xff09;, 解决了上述整体四个组织架构之间的整合关系&#xff0c;尽量实现自动化和标准化&#xff0c;其本身组成分为两个部分&#xff1a;

    • 编译器集合&#xff08;BCC 本身&#xff09;&#xff1a;这是用于编写 BCC 工具的框架
    • BCC-tools&#xff1a;这是一个不断增长的基于 eBPF 且经过测试的程序集&#xff0c;提供了使用的例子和手册(基于BCC开发的成熟工具)

    重新定义了组织结构&#xff0c;eBPF 程序组件在BCC组织方式如下&#xff1a;

    • 后端数据结构&#xff1a;用 “受限制的C语言” 编写(本身也依赖于llvm/clang进行编译成eBPF程序)。可以在单独的文件中&#xff0c;或直接作为多行字符串存储在加载器/前端的脚本中&#xff0c;以方便使用(很多方便的宏定义)。参见&#xff1a;语言参考

    • 加载器前端&#xff1a;可用非常简单的高级python/lua脚本编写

      例如pythonBPF(text&#61;&#39;BPF_program&#39;))即可加载BPF字节码到内核, 详细参见&#xff1a;语言参考

  • 层级三&#xff1a;bpftrace

    在某些用例中&#xff0c;BCC 仍然过于底层&#xff0c;例如在事件响应中检查系统时&#xff0c;时间至关重要&#xff0c;需要快速做出决定&#xff0c;而编写 python/“限制性 C” 会花费太多时间&#xff0c;因此 BPFtrace 建立在 BCC 之上&#xff0c;通过特定领域语言&#xff08;受 AWKC启发实现的一种自定义的高级语言&#xff09;提供更高级别的抽象&#xff0c;根据声明帖&#xff0c;该语言类似于 DTrace 语言实现&#xff0c;也被称为 DTrace 2.0&#xff0c;并提供了良好的介绍和例子。

    例如&#xff1a;这个单行 shell 程序统计了每个用户进程系统调用的次数&#xff08;访问内置变量、map 函数 和count()文档获取更多信息&#xff09;

    bpftrace -e &#39;tracepoint:raw_syscalls:sys_enter {&#64;[pid, comm] &#61; count();}&#39;

    局限性&#xff1a;上层的封装抽象会受限于特殊的功能需求&#xff0c;在某些场景下很难直接用一个bpftrace命令实现&#xff0c;所以还是需要BCC工具

    BCCbpftrace适用场景对比&#xff1a;

    • BCC: 开发复杂的脚本和作为后台进程使用
    • bpftrace&#xff1a;编写强大的单行程序、短小的脚本使用


  • 层级四&#xff1a;云环境中的eBPF-IOVisor

    IOVisor 是 Linux 基金会的一个合作项目&#xff0c;基于本系列文章中介绍的 eBPF 虚拟机和工具。它使用了一些非常高层次的热门概念&#xff0c;如 “通用输入/输出”&#xff0c;专注于向云/数据中心开发人员和用户提供 eBPF 技术。其重新定义了概念&#xff0c;更加模块化、组件化&#xff1a;

    • 内核eBPF虚拟机成为 “IO Visor 运行时引擎”
    • 编译器后端成为 “IO Visor 编译器后端”
    • 一般的eBPF程序被重新命名为 “IO 模块” &#xff0c;例如&#xff1a;实现包过滤器的特定 eBPF 程序称为 “IO 数据平面模块/组件”等等
    • IOVisor 项目创建了 Hover 框架&#xff0c;也被称为 “IO 模块管理器”&#xff0c;专门用于管理eBPF程序/IO模块的用户空间的后台服务程序, 目标是类似于Docker daemon发布/获取镜像的方式, 能够将IO模块推送和拉取到云端&#xff0c;分发和部署到多台主机

13. BPF运行时模块组成&#xff1f;


  • 解释器
  • JIT即时编译器&#xff1a;将BPF指令动态的转换为本地化指令
  • verifer验证器&#xff1a;用于eBPF程序指令的安全检查, 保护内核安全

1.3 eBPF可观测性方向基础


1.eBPF可观测性的术语

目前eBPF应用领域分别是网络、可观测性、安全。对于可观测性有以下术语解释&#xff1a;


  • 跟踪trace、snoop: 基于事件的跟踪&#xff0c;记录追踪系统发生的一系列事件
  • 采样sampling、profiling: 通过获取全部观测信息的子集&#xff08;定时采样&#xff09;来描绘大值的图像&#xff1b; 采样工具的优点在于性能开销比跟踪工具小&#xff0c;缺点就在于可能会遗漏部分关键事件
  • 可观测性observability&#xff1a;通过全面观测来理解一个系统&#xff0c;只要可以实现此目标就可归为此类&#xff1b;上面两种和固定计数器工具都包括在其内&#xff0c;但是不包括基准(benchmark)测量工具

2. 基础库libbcclibbpf的理解&#xff1f;

基于这两个基础库分别实现了&#xff1a;BCCbpftrace, libbpf目前已经是内核代码的一部分


3. eBPF与传统的性能分析工具的不同点&#xff1f;

eBPF是在内核层面使用非常低的损耗实现观测&#xff0c;这与传统的用户态性能分析工具有着本质区别, &#xff1a;


  • 高效&#xff1a;eBPF同时具备高效率
  • 安全性&#xff1a;eBPF同时具备生产环境安全性特点
  • 侵入性&#xff1a;eBPF已经在内核中&#xff0c;可以直接在生产环境中使用&#xff0c;无需添加新的内核组件

为什么效率高&#xff1f;


  • 举个例子&#xff0c;需要追踪当前内核I/O尺寸分布的数据&#xff0c;区别就在于&#xff1a;&#xff08;将工作都移植到到了内核中&#xff0c;减少内核、用户态之间数据复制量&#xff09;

    • 不使用BPF&#xff1a;对于每个事件都需要向缓冲区中写一条记录到perf buffer, 然后用户程序周期性拷贝所有缓冲区数据到用户态生成直方图
    • 使用BPF: 对于每次事件&#xff0c;运行BPF程序&#xff0c;只获取字节字段&#xff0c;保存在自定义的Map映射数据结构中, 用户空间一次性读取BPF直方图映射表并输出结果

    效率提升显著&#xff0c;以至于工具的额外开销减小到可以在生产环境下直接使用

为什么安全&#xff1f;


  • 相比于传统性能检测工具可能会为了高效而需要修改内核等&#xff0c;BPF采用的验证器和受限的调用更加正规和安全

相比于内核模块&#xff08;tracepoint、kprobes这些内核模块已经出现很多年了&#xff09;&#xff1a;


  • 安全性&#xff1a;有自带的安全性检查
  • 丰富的数据结构支持
  • 稳定性&#xff1a;eBPF程序CO-RE一次编译到处运行&#xff0c;BPF指令集、映射表结构、辅助函数等相关基础设施都是稳定的ABI;(当然也包括不稳定的因素&#xff0c;例如kprobes&#xff0c;但是也有对应的解决方案)
  • 原子性替换BPF程序的能力

所以适用场景也有所区别:


  • 传统性能分析工具可以作为分析的起点
  • 然后再使用BPF跟踪工具进一步分析


4. 调用栈回溯(stack-trace)


1. 函数调用栈作用&#xff1f;


  • 用于理解某些事件产生的代码路径
  • 剖析内核和用户代码&#xff0c;观测执行开销的具体位置

BPF的支持&#xff1a;


  • 专用的存储调用栈信息的映射表结构
  • 保存基于帧指针或基于ORC的调用栈回溯信息

2. 基于帧指针的栈回溯原理

一个惯例&#xff1a;


  • 函数调用栈的头部始终保存在寄存器RBP中(x86_64)
  • 函数调用的返回地址永远位于RBP的值指向的位置&#43;固定偏移量(&#43;8)

追溯过程&#xff1a;


推荐阅读
  • 本文介绍了RxJava在Android开发中的广泛应用以及其在事件总线(Event Bus)实现中的使用方法。RxJava是一种基于观察者模式的异步java库,可以提高开发效率、降低维护成本。通过RxJava,开发者可以实现事件的异步处理和链式操作。对于已经具备RxJava基础的开发者来说,本文将详细介绍如何利用RxJava实现事件总线,并提供了使用建议。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了作者在开发过程中遇到的问题,即播放框架内容安全策略设置不起作用的错误。作者通过使用编译时依赖注入的方式解决了这个问题,并分享了解决方案。文章详细描述了问题的出现情况、错误输出内容以及解决方案的具体步骤。如果你也遇到了类似的问题,本文可能对你有一定的参考价值。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
author-avatar
mobiledu2502926527
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有