[转帖]eBPF文章翻译(2)——BCC介绍(附实验环境)

ebpf,文章,翻译,bcc,介绍,实验,环境 · 浏览次数 : 0

小编点评

**安装bcc工具集合** ``` $ tools/btrfsdist.py Tracing btrfs operation latency... Hit Ctrl-C to end. ^C operation = 'read' usecs : count distribution 0 -> 1 : 0 | | 2 -> 3 : 2 |********** | 4 -> 7 : 8 |****************************************| 8 -> 15 : 1 |***** | 16 -> 31 : 4 |******************** | 32 -> 63 : 4 |******************** | operation = 'write' usecs : count distribution 0 -> 1 : 0 | | 2 -> 3 : 2 |********** | 4 -> 7 : 8 |****************************************| 8 -> 15 : 1 |***** | 16 -> 31 : 1 |******************** | 32 -> 63 : 4 |******************** | operation = 'open' usecs : count distribution 0 -> 1 : 636 |****************************************| 2 -> 3 : 22 |* | 4 -> 7 : 16 |* | 8 -> 15 : 2 | | 16 -> 31 : 1 | | operation = 'fsync' usecs : count distribution 0 -> 1 : 0 | | 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 0 | | 32 -> 63 : 0 | | 64 -> 127 : 0 | | 128 -> 255 : 0 | | 256 -> 511 : 0 | | 512 -> 1023 : 0 | | 1024 -> 2047 : 0 | | 2048 -> 4095 : 0 | | 4096 -> 8191 : 1 |**************************************** ``` **访问eBPF数据结构** ```python import bpftools.eBPF ``` **配置eBPF程序的编译方式** ```python eBPF.compile_opts = {"compiler": "eBPF"} ``` **调试程序** ```python eBPF.debug_opts = {"debug_file": "eBPF.debug.log"} ```

正文

 

eBPF学习计划可以看这里。 该篇为入门文章翻译系列第二篇,第一篇看这里。 原文名称:An introduction to the BPF Compiler Collection,原文地址:https://lwn.net/Articles/742082/

目录

  • BCC是什么
  • 一个非常快速的”Hello, World“示例
  • 更多示例
  • 未来还会有更多

BCC是什么

在本系列的前一篇文章中,我讨论了如何使用eBPF安全地运行内核内用户空间提供的代码。然而,对于新手来说,eBPF最大的挑战之一是编写程序需要编译并从内核源代码链接到eBPF库。内核开发人员可能总是可以获得内核源代码的副本,但是对于在生产环境机器或客户机器上工作的工程师来说,情况就不一样了。解决这个限制是创建BPF编译器集合的原因之一。该项目包括用于编写、编译和加载eBPF程序的工具链,以及用于调试和诊断性能问题的示例程序和久经考验的工具。

 

自2015年4月发布以来,许多开发人员都研究过BCC项目,其中113位贡献者已经一起创建并提供了令人印象深刻的工具集,包括100多个示例和随时可用的跟踪工具。例如,使用用户静态定义跟踪(USDT)探测的脚本(一种来自DTrace的在用户空间代码中放置跟踪点的机制),用于跟踪垃圾收集事件方法调用和系统调用,以及高级语言中的线程创建和销毁。许多流行的应用程序,特别是数据库,也有USDT探测,可以通过配置开关(—-enable-dtrace)启用它。这些探测,顾名思义,会在编译时,被静态地插入到用户应用程序中。在不久的将来,我将专门写一篇关于USDT探测的LWN文章。

项目文档展示了如何使用现有的脚本和工具进行全面的性能调查,而不需要编写一行代码,BCC项目库中提供了一个方便上手的教程另一个有用指南是由Brendan Gregg撰写的,他对BCC和工具补丁的贡献数量排名第二(在撰写本文时,Sasha Goldshtein的贡献数量排名第一)。

在BCC中可以使用Python和Lua语言的作为入口进行编程。使用这些高级语言,可以编写短小但富有表现力的程序,同时具备C语言所缺少的全部数据操控的优势。例如,开发人员可以将eBPF map类比为Python字典,并可以直接访问映射内容,这是通过使用BPF帮助函数,它在内部实现这个功能。这有助于降低使用eBPF的潜在开发人员的门槛,因为他们可以使用处理数据惯用的标准模式。

BCC调用LLVM Clang编译器,这个编译器具有BPF后端,可以将C代码转换成eBPF字节码。然后,BCC负责使用bpf()系统调用函数,将eBPF字节码加载到内核中。如果加载失败,例如内核验证器检查失败,则BCC提供有关加载失败原因的提示,如,“提示:如果在没有首先检查指针是否为空的情况下,从map查找中取消引用指针值,可能就会出现The 'map_value_or_null'”。这是创建BCC的另一个动机——因为很难写出明显正确的BPF程序;当你犯了错误时,BCC会通知你。

一个非常快速的”Hello, World“示例

为了演示如何快速地开始使用BCC,下面是来自BCC项目的“Hello, World!”示例程序(译者注:必须使用root权限执行)。每次运行系统函数clone()时,它都会打印到跟踪缓冲区中。我稍微修改了一下格式,以便于阅读。

#!/usr/bin/env python
from bcc import BPF

program='''
int kprobe__sys_clone(void *ctx)
{
    bpf_trace_printk("Hello, World!\n");
	return 0;
}
'''

整个eBPF程序包含在program变量中。它是运行内核里的eBPF虚拟机上的代码。函数名“kprobe__sys_clone()”的格式很重要:kprobe__前缀表示BCC工具链将一个kprobe附加到它后面的内核符号上。在这里,是sys_clone()这个符号。当调用sys_clone()时,这个kprobe会被触发,然后运行eBPF程序,bpf_trace_printk()会打印“Hello, World!”到内核的跟踪缓冲区中。

以前比较繁琐的任务是,将程序编译为eBPF字节码,并将其加载到内核。现在完全只需通过实例化一个新的BPF对象就可以处理。所有低层次的工作都是在幕后完成的,就Python bindings和BCC的libbpf库中。

函数BPF.trace_print()对内核的跟踪缓冲区文件执行阻塞读取,并将内容打印到标准输出中。这是输出内容:

    gnome-terminal--3210  [003] d..2 19252.369014: 0x00000001: Hello, World!
    gnome-terminal--3210  [003] d..2 19252.369080: 0x00000001: Hello, World!
    pool-21543 [001] d..2 19252.382317: 0x00000001: Hello, World!
    bash-21545 [002] d..2 19252.385535: 0x00000001: Hello, World!
    bash-21546 [003] d..2 19252.385752: 0x00000001: Hello, World!
    bash-21545 [002] d..2 19252.386883: 0x00000001: Hello, World!

输出内容格式说明如下:

  • kprobe触发时正在运行的应用程序名称
  • 这个应用程序的PID
  • 运行在哪个CPU核心上(在[]里面)
  • 各种进程上下文标志
  • 时间戳

最后一个字段就是我们传递给bpf_trace_printk()的“Hello, World!”字符串。倒数第二个字段包含0x00000001这个地址。通常情况下,当内核代码写入跟踪缓冲区时,系统指令trace_printk()被调用后,这个指令的指针地址将打印在该字段中。不幸的是,并没有为bpf_trace_printk()这个系统函数实现这个情况,所以总是使用硬编码的地址0x00000001

译者注: 为了更方便大家动手操作,提供了vagrant虚拟机环境,已安装bcc工具集合。 下载方式如下所示:链接: https://pan.baidu.com/s/11dsEU6Yk6KGDGNor-fbsgQ 提取码: qvhc。 使用方式如下所示:

# download the box locally
> vagrant init [ur-box-name] [the-path-where-ur-box-is-located]
> vagrant up
# BCC base dir is `/usr/share/bcc`
# BCC tool collection is in `/usr/share/bcc/tools`
# You can find the examples in `/usr/share/bcc/examples`

为大家录制了 Hello World 操作视频。

更多示例

argdist.py这个文件将探针(uprobe、kprobe、tracepoint或USDT)插入到给定的函数中,该函数可以位于内核中,也可以位于用户空间代码中。当探针被触发时,argdist.py会打印函数的参数值,以计数器或直方图的形式显示。它会一直运行,直到被用户中断。例如,下面的命令输出调用irq_handler_entry()的次数,以及引发中断的次数。

    $ tools/argdist.py -C 't:irq:irq_handler_entry():int:args->irq'
    [14:14:24]
    t:irq:irq_handler_entry():int:args->irq
    COUNT      EVENT
    12         args->irq = 45
    16         args->irq = 53
    52         args->irq = 48
    [14:14:25]
    t:irq:irq_handler_entry():int:args->irq
    COUNT      EVENT
    1          args->irq = 49
    5          args->irq = 53
    24         args->irq = 45

由于histogram选项(-H)使用桶将多个中断分组在一起,所以在这种情况下,它不如count选项(-C)有用。但是,直方图输出很有帮助的一个场景,是使用btrfsdist.py工具,该工具将Btrfs的读、写、打开和fsync操作的延迟,汇总到power-of-two桶中。

    $ tools/btrfsdist.py
    Tracing btrfs operation latency... Hit Ctrl-C to end.
    ^C

    operation = 'read'
     usecs               : count     distribution
         0 -> 1          : 775      |****************************************|
         2 -> 3          : 60       |***                                     |
         4 -> 7          : 20       |*                                       |
         8 -> 15         : 3        |                                        |
        16 -> 31         : 3        |                                        |
        32 -> 63         : 0        |                                        |
        64 -> 127        : 0        |                                        |
       128 -> 255        : 1        |                                        |
       256 -> 511        : 19       |                                        |
       512 -> 1023       : 12       |                                        |

    operation = 'write'
     usecs               : count     distribution
         0 -> 1          : 0        |                                        |
         2 -> 3          : 2        |**********                              |
         4 -> 7          : 8        |****************************************|
         8 -> 15         : 1        |*****                                   |
        16 -> 31         : 4        |********************                    |
        32 -> 63         : 4        |********************                    |

    operation = 'open'
     usecs               : count     distribution
         0 -> 1          : 636      |****************************************|
         2 -> 3          : 22       |*                                       |
         4 -> 7          : 16       |*                                       |
         8 -> 15         : 2        |                                        |
        16 -> 31         : 1        |                                        |

    operation = 'fsync'
     usecs               : count     distribution
         0 -> 1          : 0        |                                        |
         2 -> 3          : 0        |                                        |
         4 -> 7          : 0        |                                        |
         8 -> 15         : 0        |                                        |
        16 -> 31         : 0        |                                        |
        32 -> 63         : 0        |                                        |
        64 -> 127        : 0        |                                        |
       128 -> 255        : 0        |                                        |
       256 -> 511        : 0        |                                        |
       512 -> 1023       : 0        |                                        |
      1024 -> 2047       : 0        |                                        |
      2048 -> 4095       : 0        |                                        |
      4096 -> 8191       : 1        |****************************************|

未来还会有更多

这是对bbc的简短介绍。在下一篇文章中,我们将探索一些更复杂的主题,比如如何访问eBPF数据结构,如何配置eBPF程序的编译方式,以及如何调试程序,所有这些都使用Python语言作为入口。

与[转帖]eBPF文章翻译(2)——BCC介绍(附实验环境)相似的内容:

[转帖]eBPF文章翻译(2)——BCC介绍(附实验环境)

nevermosby eBPF学习计划可以看这里。 该篇为入门文章翻译系列第二篇,第一篇看这里。 原文名称:An introduction to the BPF Compiler Collection,原文地址:https://lwn.net/Articles/742082/ 目录 BCC是什么 一

[转帖]eBPF文章翻译(3)——XDP原始设计介绍

https://cloud.tencent.com/developer/inventory/600/article/1626929 eBPF学习计划可以看这里。 该篇为入门文章翻译系列第三篇,第一篇看这里,第二篇看这里。 原文名称:Early packet drop — and more — wit

[转帖]eBPF系列学习(4)了解libbpf、CO-RE (Compile Once – Run Everywhe) | 使用go开发ebpf程序(云原生利器cilium ebpf )

文章目录 一、了解libbpf1. BPF的可移植性CO-RE (Compile Once – Run Everywhere)BPF 可移植性面临的问题BPF的可移植性CO-RE (Compile Once – Run Everywhere) 2. libbpf和bcc性能对比3. 了解libbpf

[转帖]高性能网络实战:借助 eBPF 来优化负载均衡的性能

https://zhuanlan.zhihu.com/p/592981662 网络性能优化,eBPF 是如何发挥作用的呢? 本篇文章,我就以最常用的负载均衡器为例,带你一起来看看如何借助 eBPF 来优化网络的性能。 1 Nginx 负载均衡器 既然要优化负载均衡器的网络性能,那么首先就需要有一个优

[转帖]你的第一个XDP BPF 程序

https://cloud.tencent.com/developer/inventory/600/article/1626925 这是一个实战系列文章,它是eBPF学习计划里面的应用场景之网络部分,终极目标是源码级别学习云原生网络方案Cilium(声明:下文提到的BPF字样是泛指,包括cBPF和e

[转帖]BPF数据传递的桥梁——BPF Map(一)

https://cloud.tencent.com/developer/inventory/600/article/1644458 这是一个实战系列文章,它是eBPF学习计划里面的应用场景之网络部分,终极目标是源码级别学习云原生环境下使用eBPF的场景,比如Cilium、Falco等(声明:下文提到

[转帖]Libbpf-tools —— 让 Tracing 工具身轻如燕

https://cloud.tencent.com/developer/article/1678208?areaSource=103001.2&traceId=rX8kmZPurwFtXqEtY-bY- 本文被 1 个清单收录,推荐清单 Linux超能力eBPF技术学习分享 本篇文章概述了 BPF

[转帖]eBPF 完全入门指南.pdf(万字长文)

https://zhuanlan.zhihu.com/p/492185920 图片 eBPF 源于 BPF[1],本质上是处于内核中的一个高效与灵活的虚类虚拟机组件,以一种安全的方式在许多内核 hook 点执行字节码。BPF 最初的目的是用于高效网络报文过滤,经过重新设计,eBPF 不再局限于网络协

[转帖]eBPF监控工具bcc系列一启航

https://blog.51cto.com/u_15333820/3453313 在eBPF篇中,我们知道虽然可用 C 来实现 BPF,但编译出来的却仍然是 ELF 文件,开发者需要手动析出真正可以注入内核的代码。工作有些麻烦,于是就有人设计了 BPF Compiler Collection(BC

[转帖]eBPF 技术实践:加速容器网络转发,耗时降低 60%+

https://my.oschina.net/u/6150560/blog/5587717 背景 Linux 具有功能丰富的网络协议栈,并且兼顾了非常优秀的性能。但是,这是相对的。单纯从网络协议栈各个子系统的角度来说,确实做到了功能与性能的平衡。不过,当把多个子系统组合起来,去满足实际的业务需求,功