LinuxBPF学习笔记 - 基本概念 [1]

Posted 宣之于口

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LinuxBPF学习笔记 - 基本概念 [1]相关的知识,希望对你有一定的参考价值。

【Linux】BPF学习笔记 - 基本概念 [1]

本学习笔记来自于阅读 Brendan Gregg的《BPF Performance Tools》

一、介绍

数据包筛选器(BPF) 是一种内核执行引擎,用于处理虚拟指令集,并且最近进行了扩展(又称eBPF),这使BPF变成了通用执行引擎,可用于多种用途,包括创建高级性能分析工具。

这是一种在各种内核和应用程序事件上运行小型程序的方法。 如果您熟悉javascript,则可能会看到一些相似之处:JavaScript允许网站在浏览器事件(例如鼠标单击)上运行微型程序,从而启用各种新的基于Web的应用程序。 BPF允许内核在系统和应用程序事件(例如磁盘I/O)上运行微型程序,并启用新的系统技术。 它使内核完全可编程,从而使用户(包括非内核开发人员)能够自定义和控制他们的系统,以解决实际问题。

根据这本书介绍BPF设计了以下工具检查对应组件:

二、术语

1. Tracing

Tracing是基于事件的记录, 这些事件可以是静态或动态,基于仪器(instrumentation)或计时器(timer)的。跟踪器的标志是其记录原始事件和事件元数据的能力. 目前存在一些跟踪器, 如:

  • Linux strace: 记录并打印系统调用事件

  • Linux top: 不跟踪事件,而是使用固定的统计计数器来测量事件,然后打印摘要

这样的数据可能非常庞大,可能需要进行后续处理成摘要. BPF可以在事件上运行小型程序,以进行自定义的实时统计摘要或其他操作,从而避免进行昂贵的后续处理。

2. Sampling

Sampling是指采取部分测量来绘制目标粗略图片的工具, 这也称为Profiling

有一个称为profile的BPF工具,它可以获取基于计时器的运行代码样本。 例如,它可以每十毫秒采样一次,或者换句话说,它每秒可以采样一百个样本(在每个CPU上)。 采样器的一个优点是它们的性能开销可以低于跟踪器的性能开销,因为它们仅测量大得多的一组事件中的一个。 缺点是采样仅能提供粗略的图像,并且会漏掉事件。

3. Instrumentation[插桩]

一般指的是获取计算机软件或者硬件状态的数据的技术, 常用实现的方法是将一段代码注入到目标程序中,从注入目标程序的时间点的角度可分为两种类型:静态插桩、动态插桩. 常用于程序监控与跟踪. (摘自百度百科).

Dynamic instrumentation: 也称为 Dynamic tracing, 这是将检测点插入实时软件的能力。 BPF工具经常使用它来检测内核和应用程序功能的开始和结束. 动态插桩存在一个问题: 当软件版本更新时, 它的instruments方法可以被被删除或重命名, 这称为接口稳定性. 但是升级内核或应用程序软件后,可能突然发现BPF不再正常工作, 也许他会打印出无法找到 instrument 功能的错误,或者根本没有任何输出.

Static instrumentation: 解决动态插桩的一个方案是切换到静态工具,其中将稳定的事件名称编码到软件中,并由开发人员维护。BPF跟踪支持用于内核静态检测的跟踪点和USDT(用户静态定义的跟踪, 也称为用户标记. 用于用户级静态检测). 静态检测的缺点是这些检测点成为开发人员的维护负担,因此,如果存在的话,通常数量会受到限制。

三、传统性能分析工具

下表总结了用于检查对应组件的传统工具,以及BPF跟踪是否可以观察到这些组件, 例如内核CPU调度程序,虚拟内存,文件系统等

四、BPF跟踪工具

以下介绍主要两种BPF的提供高级语言的前端. BCCbpftrace是互补关系, bpftrace是强大的单行代码和自定义短脚本的理想选择,而BCC更适合使用其他库的复杂脚本和守护程序。开发中还有另一个BPF前端,称为ply,其设计轻巧且需要的依赖性极小,这使其非常适合嵌入式Linux环境。

1. bpftrace

bpftrace是一个较新的前端,它为开发BPF工具提供了专用的高级语言。 bpftrace代码非常简洁, 其建立在libbcc和libbpf库上。

示例1:OPEN(), 注意, bpftrace在系统范围内进行跟踪,因此将看到使用open的任何应用程序

# 事件: 设置一个跟踪点 syscalls:sys_enter_open
bpftrace -e 'tracepoint:syscalls:sys_enter_open  printf("%s %s\\n", comm, str(args->filename)); '

Attaching 1 probe...
# 输出显示了 进程名称 + 传递给open调用的文件名
slack /run/user/1000/gdm/Xauthority
slack /run/user/1000/gdm/Xauthority
slack /run/user/1000/gdm/Xauthority
slack /run/user/1000/gdm/Xauthority
^C”

但是该结果比预期的要少, 猜测缺少一些open(2) syscall事件, 内核支持open的几种变体,而上述只追踪了其中一种

# 事件: 通过使用 -l 和通配符来使用bpftrace列出所有打开的跟踪点
bpftrace -l 'tracepoint:syscalls:sys_enter_open*'

tracepoint:syscalls:sys_enter_open_by_handle_at
tracepoint:syscalls:sys_enter_open
tracepoint:syscalls:sys_enter_openat”

以下显示的是这些跟踪点的计数,可以看出 BPF程序在内核中有效地计算了该摘要.

bpftrace -e 'tracepoint:syscalls:sys_enter_open*  @[probe] = count(); '

Attaching 3 probes...
^C
# 这确认了 openat 系统调用被更频繁地调用,在跟踪时被调用308次,而 open 系统调用仅被调用了5次
@[tracepoint:syscalls:sys_enter_open]: 5
@[tracepoint:syscalls:sys_enter_openat]: 308”

将该代码保存到可执行文件中, opensnoop, 可用于对故障软件进行故障排除,例如该软件正尝试从错误的路径打开文件,以及根据访问权限确定配置文件和日志文件的存放位置。它还可以识别一些性能问题,其中文件打开过快或错误位置检查得过于频繁。

# 保存为脚本文件
opensnoop.bt

Attaching 3 probes...
Tracing open syscalls... Hit Ctrl-C to end.
PID    COMM               FD ERR PATH
2440   snmp-pass           4   0 /proc/cpuinfo
2440   snmp-pass           4   0 /proc/stat
25706  ls                  3   0 /etc/ld.so.cache”

总结: BPF程序是在单引号内定义的,一旦按Enter键运行bpftrace命令,它就会编译并运行。bpftrace还激活了open跟踪点。 当按Control-C停止命令时,open跟踪点被停用,并且删除了该小型BPF程序。

BPF跟踪工具的按需检测就是这样工作的:它们仅在命令的生命周期内激活并运行,生命周期可以短至几秒钟。

2. BCC

BCC(BPF编译器集合)是为BPF开发的第一个高级跟踪框架。 它提供了一个C编程环境,用于编写内核BPF代码。同时可以用其他语言(Python,lua和C ++) 编写用户级界面。它也是libbcc和当前libbpf库的起源,它们提供了使用BPF程序检测事件的功能。 BCC存储库还包含70多个BPF工具,用于性能分析和故障排除。 您可以在系统上安装BCC,然后运行提供的工具,而无需自己编写任何BCC代码。

示例1: 基于BCC的execsnoop工具, 专门用于为追踪短时进程而设计

execsnoop -t
# 输出结果: 在跟踪时执行了的进程的基本信息,包括进程 PID、父进程 PID、命令行参数等
TIME(s) PCOMM        PID    PPID   RET ARGS
0.437   run          15524  4469     0 ./run
0.438   bash         15524  4469     0 /bin/bash
0.440   svstat       15526  15525    0 /command/svstat /service/httpd”

示例2: 基于BCC的biolatency工具, 该输出对高延迟非常敏感,因为它具有服务级别协议,可以在一定毫秒内交付请求。在运行biolatency工具时,将对块I/O事件进行检测,并由BPF计算和汇总其延迟。当工具停止运行(Ctrl-C)时,将打印摘要. 如下图所示, 在512到1023毫秒范围内,有11个I/O。这些速度非常慢,被称为延迟异常值

biolatency -m
Tracing block device I/O... Hit Ctrl-C to end.
^C
# 打印了各个时间段的 I/O数
     msecs               : count     distribution
         0 -> 1          : 16335    |****************************************|
         2 -> 3          : 2272     |*****                                   |
         8 -> 15         : 4328     |**********                              |
        16 -> 31         : 3379     |********                                |
        ...
       512 -> 1023       : 11       |                                        |

示例3: 在bpftrace中提到过opensnoop, 其BCC版本可支持多种操作模式 - 可以使用不同的命令行选项来调用

# opensnoop -h
usage: opensnoop [-h] [-T] [-x] [-p PID] [-t TID] [-d DURATION] [-n NAME]
                    [-e] [-f FLAG_FILTER]

Trace open() syscalls

optional arguments:
  -h, --help            show this help message and exit
  -T, --timestamp       include timestamp on output
  -x, --failed          only show failed opens
  -p PID, --pid PID     trace this PID only
  -t TID, --tid TID     trace this TID only”
...

总结: BCC工具通常支持几种这样的选项来更改其行为,从而使其比bpftrace工具更具通用性

参考文章

主要书籍: BPF Performance Tools

GCC 地址: https://github.com/iovisor/bcc

bpftrace 地址: https://github.com/iovisor/bpftrace

以上是关于LinuxBPF学习笔记 - 基本概念 [1]的主要内容,如果未能解决你的问题,请参考以下文章

LinuxBPF学习笔记 - 调试技术[4]

LinuxBPF学习笔记 - 调试技术[4]

LinuxBPF学习笔记 - 技术背景[2]

LinuxBPF学习笔记 - 技术背景[2]

LinuxBPF学习笔记 - BCC工具[6]

LinuxBPF学习笔记 - BCC工具[6]