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的提供高级语言的前端. BCC
与bpftrace
是互补关系, 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]的主要内容,如果未能解决你的问题,请参考以下文章