ebpf学习

这篇具有很好参考价值的文章主要介绍了ebpf学习。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

学习ebpf相关知识
参考资料:
awesome-ebpf

初识

最开始接触到的是经典bpf,即cbpf,可以通过生成的字节码给raw socket设定过滤器,这过程中了解到了ebpf,被他的强大所吸引,过去我就对内核观测方面缺少了解,而现有的一些手段显的有点麻烦,不是那么易用,我当时就感觉ebpf可能可以符合我的要求。看gpt的回答:

灵活性方面,eBPF是目前最灵活的观测内核行为的工具之一。它允许用户编写自定义的观测逻辑,并且可以在不需要重新编译内核的情况下动态加载和卸载观测程序。

当时尝试去搞ebpf,但是由于改了内核选项之后,内核跑不起来了,加之工作太忙,因此就搁置了,这段时间又捡起来

准备

本来想找linux内核之旅的入门教程的,但是去看了gitee和github,资料都不知道去哪了,无奈,只能重新找了awesome ebpf来看了。这个项目中有很多的资料链接,非常多,可以先挑几个看。

ebpf.io介绍

先看ebpf.io的介绍,可以设置中文。
这里摘录一些我觉得有必要记录的:

如何编写 eBPF 程序 ?

在很多情况下,eBPF 不是直接使用,而是通过像 Cilium、bcc 或 bpftrace 这样的项目间接使用,这些项目提供了 eBPF 之上的抽象,不需要直接编写程序,而是提供了指定基于意图的来定义实现的能力,然后用 eBPF 实现。
如果不存在更高层次的抽象,则需要直接编写程序。Linux 内核期望 eBPF 程序以字节码的形式加载。虽然直接编写字节码当然是可能的,但更常见的开发实践是利用像 LLVM 这样的编译器套件将伪 c 代码编译成 eBPF 字节码如果不存在更高层次的抽象,则需要直接编写程序。

开发工具链

bcc

BCC 是一个框架,它允许用户编写 python 程序,并将 eBPF 程序嵌入其中。该框架主要用于应用程序和系统的分析/跟踪等场景,其中 eBPF 程序用于收集统计数据或生成事件,而用户空间中的对应程序收集数据并以易理解的形式展示。运行 python 程序将生成 eBPF 字节码并将其加载到内核中。

bpftrace

bpftrace 是一种用于 Linux eBPF 的高级跟踪语言,可在较新的 Linux 内核(4.x)中使用。bpftrace 使用 LLVM 作为后端,将脚本编译为 eBPF 字节码,并利用 BCC 与 Linux eBPF 子系统以及现有的 Linux 跟踪功能(内核动态跟踪(kprobes)、用户级动态跟踪(uprobes)和跟踪点)进行交互。bpftrace 语言的灵感来自于 awk、C 和之前的跟踪程序,如 DTrace 和 SystemTap。

eBPF Go 语言库

eBPF Go 语言库提供了一个通用的 eBPF 库,它将获取 eBPF 字节码的过程与 eBPF 程序的加载和管理进行了解耦。eBPF程序通常是通过编写高级语言,然后使用 clang/LLVM 编译器编译成 eBPF 字节码来创建的。

libbpf C/C++ 库

libbpf 库是一个基于 C/ c++ 的通用 eBPF 库,它可以帮助解耦将 clang/LLVM 编译器生成的 eBPF对象文件的加载到内核中的这个过程,并通过为应用程序提供易于使用的库 API 来抽象与 BPF 系统调用的交互。

cilium的介绍

链接:BPF and XDP Reference Guide
在开发工具章节的安装,比如bpftool,llvm等,在内核编译章节,提供了一些编译内核相关的内容。

内核文档

BPF Documentation

Brendan Gregg’s Blog 的介绍

Learn eBPF Tracing: Tutorial and Examples

书籍

Learning eBPF

这里ebpf.io还推荐了几本书,我准备先看下Learning eBPF,电子版在这,看起来像是一本入门书籍。而且还有配套的示例代码。我在我的Mac-mini上装了一个lima,用来跑这个代码。我看这里面用了quem,感觉如果不是为了后续实际落地,我可以不用折腾环境了。。。

What is eBPF?

另外还有一本同一个作者在更早写的《what-is-ebpf》,这里有中文翻译版。

交互式环境

都在这个页面
Getting started with eBPF
Learning eBPF Tutorial

视频

Tutorial: Getting Started with eBPF - Liz Rice, Isovalent

基础知识学习

学习环境搭建

我发现资料太多了,打算先从《Learning eBPF》开始,刚好作者提供了环境。我打算以树莓派真实环境为主,毕竟是后面打算落地应用的,以虚拟环境为辅。
在Brendan Gregg的博客中提到,初级是运行 bcc tools,中级开发bpftrace tools,高级直接参与到这两个工具的开发,因此我打算先从bcc开始。而《Learning eBPF》作者提供的环境里,各种环境都准备好了,像bcc,bpftool,libbpf等等全部都ok,而且内核的各种选项也都开了,而且使用了quem,可以模拟arm64设备,十分方便用来前期学习。

书籍阅读

详见《Learning eBPF》读书笔记

项目落地流程整理

如果想把ebpf在项目落地,需要考虑的有以下方面问题
1.嵌入式设备的交叉编译
2.主机设备网络受限,无法使用apt等工具
3.编写程序以及排查定位编写程序的难度问题

目前大概有两条路:
1.使用bpftool加载ebpf程序到内核,但是这样就没法写用户态程序交互了
2.使用libbpf完成全套工作,优点是可扩展性高,缺点是环境搭建可能更麻烦。

环境搭建

内核编译

毫无疑问,内核需要进行配置,以运行ebpf
我这里5.10.110的默认配置如下:

$ cat .config|grep BPF
CONFIG_CGROUP_BPF=y
CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_ARCH_WANT_DEFAULT_BPF_JIT=y
# CONFIG_BPF_UNPRIV_DEFAULT_OFF is not set
# CONFIG_BPF_PRELOAD is not set
CONFIG_NETFILTER_XT_MATCH_BPF=m
# CONFIG_BPFILTER is not set
# CONFIG_NET_CLS_BPF is not set
# CONFIG_NET_ACT_BPF is not set
# CONFIG_BPF_JIT is not set
# CONFIG_BPF_STREAM_PARSER is not set
CONFIG_LWTUNNEL_BPF=y
CONFIG_HAVE_EBPF_JIT=y
CONFIG_BPF_LIRC_MODE2=y
CONFIG_BPF_EVENTS=y
# CONFIG_BPF_KPROBE_OVERRIDE is not set
# CONFIG_TEST_BPF is not set

上面需要开启JIT,以获取更高的运行效率,另外还需要再开启BTF,支持CO-RE。

CONFIG_BPF_JIT
CONFIG_DEBUG_INFO_BTF

ok,不出意外的话会出现意外,编译失败:

FAILED: load BTF from vmlinux: Unknown error -22make: *** [Makefile:1179: vmlinux] Error 255

看了下是tools/bpf/resolve_btfids直接失败了。。。。
后面用6.1内核一次成功,我怀疑是交叉编译的支持不太好,我选择放弃,选6.1了

bcc

本来我打算在树莓派自行从源码搭建bcc的,但是看了下安装文档,感觉有点麻烦,所以直接用Learning eBPF中提供的虚拟环境了。
感受下22.04依赖库:

# For Jammy (22.04)
sudo apt install -y zip bison build-essential cmake flex git libedit-dev \
 libllvm14 llvm-14-dev libclang-14-dev python3 zlib1g-dev libelf-dev libfl-dev python3-setuptools \
 liblzma-dev libdebuginfod-dev arping netperf iperf

环境变量

shell:

#!/bin/bash
ROOT_PATH=/home/wsl/project/raspberry_pi/
export ZLIB_ROOT_PATH=${ROOT_PATH}/ebpf/zlib-1.3/
export LIBELF_ROOT_PATH=${ROOT_PATH}/ebpf/elfutils-0.190/
ZLIB_INC=${ZLIB_ROOT_PATH}/output/usr/local/include
ZLIB_LIB=${ZLIB_ROOT_PATH}/output/usr/local/lib
LIBELF_INC=${LIBELF_ROOT_PATH}/libelf/output/usr/local/include
LIBELF_LIB=${LIBELF_ROOT_PATH}/libelf/output/usr/local/lib
export ZLIB_INC ZLIB_LIB LIBELF_INC LIBELF_LIB

zlib

github仓库
编译脚本:

#!/bin/bash
make clean
CHOST=aarch64-linux-gnu ./configure \
--static #最好编译成静态的,因为后面feature检查不加-lz
make -j4
make DESTDIR=output install

libelf

libelf隶属于elfutils。
直接编译,然后报了这个错误"_FORTIFY_SOURCE" redefined,然后参照github的解答,修改了configure参数,编译脚本如下,可以编译通过了。 后面发现可以直接编译通过了,神奇

#!/bin/bash
source ../../env.sh
echo "zlib inc is $ZLIB_INC"
echo "zlib lib is $ZLIB_LIB"
./configure --host=aarch64-linux-gnu \
CFLAGS="-I${ZLIB_INC}" \
LDFLAGS="-L${ZLIB_LIB}" LIBS="-lz"
make -j4
make DESTDIR=output install

libbpf

知识了解:【译】 Libbpf:初学者指南
libbpf的起始代码示例: libbpf-bootstrap
包含libbpf相关基础知识和例子的博客
libbpf依赖libelf和zlib,不过这个库应该是还好,应该是用gcc可以编出来
然后libbpf本身应该也是可以用gcc编出来,但是我看用libbpf写的程序却是用clang编的,主要我用的时候要交叉编译,,,,
其实libbpf在linux源码中也有,要不是看makefile我都不知道,位于tools/lib/bpf/
官方编译指南

编译脚本

#!/bin/bash
BUILD_STATIC_ONLY=y CROSS_COMPILE=aarch64-linux-gnu- NO_PKG_CONFIG=1 DESTDIR=output make install

libbpf-bootstrap

libbpf-bootstrap在树莓派安装失败了,但在虚拟机环境上却一次成功,,,不知道是不是内核支持的问题。不过最终在树莓派上我也是要交叉编译的,不折腾了。

bpftool

在内核源码中就有,位于/tools/bpf/bpftool/。而且看makefile是可以连libbpf一起编的。依赖libelf和zlib。
最开始时特性检查是这样的:

Auto-detecting system features:
...                        libbfd: [ OFF ]
...        disassembler-four-args: [ OFF ]
...                          zlib: [ on  ]
...                        libcap: [ OFF ]
...               clang-bpf-co-re: [ OFF ]

我就在想co-re为啥不支持呢,后来把feature检查的打印放开,发现是主机没装llvm和clang。。。。装好后再编就ok了。
还有一个就是,我编译找不到库,发现是用了CFLAGS,实际应该用EXTRA_CFLAGS,以及EXTRA_LDFLAGS。
OK,继续编译,应该是去编libbpf了,问题又来了,提示找不到libelf,我明明都编了,只好加打印分析了。
在tools/bpf/bpftools当中,CFLAGS在Makefile中有额外赋值,LDFLAGS无额外赋值,两者都会+=EXTAR_XXFLAGS,但是在子目标libbpf中,未传递任何变量,也就是说只有最开始命令行指定的参数才会通过MAKEFLAGS传递到子makefile中去。在tools/lib/bpf/Makfile中,CFLAGS与bpftool中类似,因此CFLAGS无误,但是LDFLAGS无额外赋值。
实际libbpf在编译时include的了Makefile.feature,在build/Makefile.feature中,实际make的命令行参数中,CFLAGS赋值为EXTRA_CFLAGS,LDFLAGS无赋值,如下:

feature_check = $(eval $(feature_check_code))
define feature_check_code
  feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CC="$(CC)" CXX="$(CXX)" CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" CXXFLAGS="$(EXTRA_CXXFLAGS) $(FEATURE_CHECK_CXXFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
endef

在在build/feature/Makefile中,直接使用CFLAGS,LDFLAGS,无任何额外赋值。因此决定调整编译参数。编译ok,但是又报错了,

/bpftool-bootstrap btf dump file /home/wsl/project/raspberry_pi/linux/vmlinux format c > vmlinux.h
/bin/sh: 1: ./bpftool-bootstrap: Exec format error
make[1]: *** [Makefile:139: vmlinux.h] Error 126
make: *** [Makefile:71: bpf/bpftool] Error 2

看下这两个文件:

wsl@My-win:~/project/raspberry_pi/linux/tools$ file bpf/bpftool/bpftool-bootstrap
bpf/bpftool/bpftool-bootstrap: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=6de9b18d3cb85a30d39cd8eebb37836397a08dd8, for GNU/Linux 3.7.0, not stripped
wsl@My-win:~/project/raspberry_pi/linux/tools$ file /home/wsl/project/raspberry_pi/linux/vmlinux
/home/wsl/project/raspberry_pi/linux/vmlinux: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), statically linked, BuildID[sha1]=1b1c20a248667d9a82dbfb87488660e92ca992f4, not stripped

好吧,都是ARM64的,所以这个脚本,交叉编译真的能行吗。。。
我直接把bpftool-bootstrap拷贝到已经换好内核的树莓派,然后准备按照makefile中的提示执行,这个工具依赖libelf,所以需要在树莓派安装依赖库
按照libbpf-的编译指南,ubuntu应该装这些:

$ apt install clang libelf1 libelf-dev zlib1g-dev

我没装clang,后面再说吧。讲道理,本来应该我把我自己交叉编译的库拷过去的,直接install,也行吧。。。


bpftool-bootstrap btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h

这个命令和之前看learnning ebpf中提到的生成vmlinux.h的命令几乎一模一样,除了执行的进程变成了bpftool-bootstrap。
好吧,这个vmlinux ok之后又有新的错误

./bpftool-bootstrap gen skeleton profiler.bpf.o > profiler.skel.h
/bin/sh: 1: ./bpftool-bootstrap: Exec format error

感觉很生气,去看了别人的文章,都是能编译过的,然后换了6.1的内核,bpftool,libbpf,包括带btf选项的内核全部一次编译通过了。。。。
分别对比Makefile有如下发现:
1.编译bpftool不再检查zlib
2.编译libbpf不再检查libelf zlib,且编译已经完全不依赖这两个库
3.bpftool-bootstrap变成了bpftool,而且是直接host编译的,不是交叉编译的:

$ file /home/wsl/project/raspberry_pi/linux_6.1.y/tools/bpf/bpftool/bootstrap/bpftool
/home/wsl/project/raspberry_pi/linux_6.1.y/tools/bpf/bpftool/bootstrap/bpftool: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=e9f7b79931f1f08a97a24ae93a014750bce6c04e, for GNU/Linux 3.2.0, with debug_info, not stripped

更绝望的是,5.11就支持交叉编译了,我用的是5.10,生产环境也是5.10,啊啊啊啊啊阿啊啊啊啊
编译脚本:文章来源地址https://www.toymoban.com/news/detail-816915.html

#!/bin/bash                                                                                                                              
source ../../env.sh                                                                                                                      
echo "zlib inc is $ZLIB_INC"                                                                                                            
echo "zlib lib is $ZLIB_LIB"                                                                                                             
echo "libelf inc is $LIBELF_INC"
echo "libelf lib is $LIBELF_LIB"                                                                                                         
echo "vmlinux path is $VMLINUX_PATH"                                                                                                     
make bpf/bpftool V=1 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- EXTRA_CFLAGS="-I${ZLIB_INC} -I${LIBELF_INC}" LDFLAGS="-L${ZLIB_LIB} -L${LIBELF_LIB}" VMLINUX_H=${VMLINUX_PATH} -j4

到了这里,关于ebpf学习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [RSA议题分析] eBPF Warfare - Detecting Kernel & eBPF Rootkits with Tracee

    eBPF在恶意活动检测方面仍是未知领域。随着威胁的不断出现,我们需要采取主动。参与者将了解到不同类型的rootkits,它们的攻击流程,它们的运作方式以及如何检测它们。最后,他们将学习如何使用Tracee,这是一个利用eBPF来检测这些威胁并在攻击者面前获得优势的开源工具

    2024年02月07日
    浏览(36)
  • 【Learning eBPF-0】引言

    本系列为《Learning eBPF》一书的翻译系列。 (内容并非机翻,部分夹带私货)笔者学习自用,欢迎大家讨论学习。 转载请联系笔者或注明出处,谢谢。 各个章节内容: 1)背景介绍:为啥 eBPF 很吊,以及内核如何支持这种超能力的。 2)给出一个 “Hello World” 例子,介绍 eB

    2024年04月08日
    浏览(42)
  • ebpf简介

    eBPF 是什么呢? 从它的全称“扩展的伯克利数据包过滤器 (Extended Berkeley Packet Filter)” 来看,它是一种数据包过滤技术,是从 BPF (Berkeley Packet Filter) 技术扩展而来的。顾名思义BPF来源于伯克利大学, 最早应用于网络数据包过滤器,它比当时最先进的抓包技术快20倍,其主要得

    2024年02月07日
    浏览(34)
  • eBPF运行时安全

    eBPF作为当前linux系统上最为炙手可热的技术,通常被用于网络流量过滤和分析、系统调用跟踪、性能优化、安全监控,当下比较知名的项目有Cilium、Falco等。 Cilium 是一个开源的容器网络和安全性项目,致力于提供高效的容器通信和强大的安全性功能,Cilium 基于eBPF、XDP、TC等

    2024年01月21日
    浏览(52)
  • 1.1 什么是eBPF?(上)

        大多数介绍eBPF的文章都是用“eBPF是一种革命性的内核技术”来描绘的。这样讲一点也不夸张。因为它允许在Linux的内核中执行沙盒程序,在不改变内核源码或加载内核模块的前提下直接地,安全地,快捷地扩展内核,并改变内核的行为。可以想像在运行时,将用户空间的

    2024年02月06日
    浏览(26)
  • eBPF 入门开发实践教程十一:在 eBPF 中使用 libbpf 开发用户态程序并跟踪 exec() 和 exit() 系统调用

    eBPF (Extended Berkeley Packet Filter) 是 Linux 内核上的一个强大的网络和性能分析工具。它允许开发者在内核运行时动态加载、更新和运行用户定义的代码。 在本教程中,我们将了解内核态和用户态的 eBPF 程序是如何协同工作的。我们还将学习如何使用原生的 libbpf 开发用户态程序,

    2024年02月07日
    浏览(46)
  • Linux之ebpf(1)基础使用

    Author: Once Day Date: 2024年4月20日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文章可以参考专栏:Linux基础知识_Once-Day的博客-CSDN博客。 参考文章: eBPF 完全入门指南.pdf(万字长文) - 知乎 (zhih

    2024年04月26日
    浏览(23)
  • 3.1 Android eBPF代码仓解读

    前面已经介绍,Android从9.0版本开始支持eBPF,并且主要用于网络及CPU性能的监控上。它包含一个eBPF加载器和库。加载器在Andoroid init启动/system/etc/bpf/下的所有eBPF程序,ebpf程序在完成加载后,内核ebpf程序进行verify和attach,顺利的话,最终,ebpf程序会被hook或插入到指定的内核函

    2024年02月09日
    浏览(35)
  • 基于 eBPF 的 Kubernetes 可观测实践

    可观测是为了解决问题,所以在聊可观测之前,应先对问题排查的普适原则进行了解。 问题排查的原则 以排查系统问题为例,要理解系统,要先关注基础知识,理解编程语言基本的计算机科学知识,关注系统大图比如架构部署和重大流程,要关注运行细节,要对核心功能的

    2024年01月19日
    浏览(57)
  • 2.8 Android ebpf帮助函数解读(七)

    121.long bpf_read_branch_records(struct bpf_perf_event_data * ctx , void * buf , u32 size , u64 flags ) 描述:对于附加到 perf 事件的 eBPF 程序,检索与 ctx 关联的分支记录(struct perf_branch_entry),并将其存储在 buf 指向的缓冲区中,最大大小为size字节。 返回值:成功则返回写入buf的字节数。错误则

    2024年02月15日
    浏览(77)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包