之前尝试了两种方法使用ePBF对内核数据进行提取和分析,第一个是bcc,具体信息见我的另一个blog:eBPF初体验_mozart1756的博客-CSDN博客。

再复习一下大致的步骤:

首先,确认内核包含如下编译选项:

CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
# [optional, for tc filters]
CONFIG_NET_CLS_BPF=m
# [optional, for tc actions]
CONFIG_NET_ACT_BPF=m
CONFIG_BPF_JIT=y
# [for Linux kernel versions 4.1 through 4.6]
CONFIG_HAVE_BPF_JIT=y
# [for Linux kernel versions 4.7 and later]
CONFIG_HAVE_EBPF_JIT=y
# [optional, for kprobes]
CONFIG_BPF_EVENTS=y
# Need kernel headers through /sys/kernel/kheaders.tar.xz
CONFIG_IKHEADERS=y

这样保证内核是一个支持ebpf的内核,否则无论什么形式的ebpf程序,都无法在该内核上正常运行。

第二,安装必要的编译工具,至少要安装clang和llvm,我目前安装的版本是clang-12,同时,bcc是在python下运行,还有安装python。

最后,准备bcc的代码和运行环境:

git clone https://github.com/iovisor/bcc.gitmkdir bcc/build; cd bcc/build
cmake ..
make
sudo make install
cmake -DPYTHON_CMD=python3 .. # build python3 binding
pushd src/python/
make
sudo make install
popd

最后,看一下运行的结果(以biolatency.py为例):

sudo python3 biolatency.pyTracing block device I/O... Hit Ctrl-C to end.^Cusecs               : count     distribution0 -> 1          : 0        |                                        |2 -> 3          : 0        |                                        |4 -> 7          : 0        |                                        |8 -> 15         : 0        |                                        |16 -> 31         : 0        |                                        |32 -> 63         : 3        |**                                      |64 -> 127        : 15       |***********                             |128 -> 255        : 50       |*************************************   |256 -> 511        : 54       |****************************************|512 -> 1023       : 49       |************************************    |1024 -> 2047       : 3        |**                                      |2048 -> 4095       : 4        |**                                      |4096 -> 8191       : 33       |************************                |8192 -> 16383      : 2        |*                                       |

bcc的有点是操作简单,容易上手,而且,由于bcc是在待测的内核上编译和运行,所以没有内核跨版本的兼容性问题。缺点也是由于由于bcc是在待测的内核上编译和运行,会消耗很多的系统资源,在一些场景下并不适用。

我对ebpf的第二个尝试是适用C代码直接在内核代码树中编写ebpf程序,代码的位置在内核代码的sample/bpf目录下,你需要把你的代码放到这个目录下,每个工具应该包括两个c文件,一个运行在内核空间,另一个运行在用户空间,然后在Makefile中添加相应的信息,最后运行

make M=sample/bpf编译即可。

我做了5个实时内核相关的小工具,包括:

  • 中断响应时间
  • 任务抢占和切换时间
  • 死锁解除时间
  • 信号混洗时间
  • 消息传递时间

这种方式的好处是比较简单,对于C语言比较友好,且仅需编译一次,运行时资源消耗较少。缺点是兼容性不好,内核版本更换之后,工具无法正常使用,需要移植和适配。

既然说到了兼容性问题,那内核的兼容性问题是什么的?ebpf工具大部分是依赖于内核的数据结构的,比如我从task_struct这个结构中读取pid这个字段,在4.19内核中,这个字段在task_struct offset 8 地址,在5.4内核,也许会由于版本的演进,前面多了16个自己的字段,那么pid就变成task_struct offset 24(这是个例子,pid在这两个版本之间并没有变换位置)。或者,某些字段的名字变了,比如thread_structfs 字段(获取 thread-local storage 用), 在 4.6 到 4.7 内核升级时就被重命名为了 fsbase

这些问题,都导致了ebpf的兼容性和移植性的问题。

目前社区致力于使用BTF和libbpf来达到CO-RE(compile once -- run everywhere)的效果,其中BTF在内核编译的时候记录了内核的调试信息,比如内核的结构,字段,偏移量等信息,同时,这些信息内核会输出到/sys/kernel/btf/vmlinux中,clang在编译ebpf的程序时,会对ebpf程序所使用的内核结构字段做一个记录,比如如果想访问 task_struct->pid,那clang 将做如下记录:这是一个位于结构体 struct task_struct 中、类型为 pid_t、名为 pid 的字段。libbpf会查看 ebpf 程序记录的 BTF 的重定位信息,对ebpf中使用内核数据的部分进行地址的重定位。这个就是CO-RE解决兼容和移植问题的方法。具体的细节描述见下面两篇blog:

BPF 可移植性和 CO-RE(一次编译,到处运行)_米开朗基杨的博客-CSDN博客

BPF BTF 详细介绍_dwh0403的博客-CSDN博客_bpf是什么文件格式

在bcc中,由一个目录为libbpf-tools,就是bcc使用CO-RE来使用C语言编写可移植的ebpf程序,我对此做了一些尝试:

1,获取最新的bcc代码
git clone https://github.com/iovisor/bcc.git
2,在bcc中获取libbpf和bpftool的代码
git submodule update --init --recursive此时你再查看bcc/libbpf-tools/bpftool和bcc/src/cc/libbpf中也已经下载好了需要使用的源码。
回到bcc/libbpf-tools,运行make进行编译。

此时,我遇到了一个编译错误,没有函数__builtin_preserve_type_info的定义。

查阅了一些资料,找到__builtin_preserve_type_info是一个clang提供的builtin函数,需要至少clang12及以上的版本,我检查了一下我使用设备的clang的版本,发现我安装了两个clang,一个是clang10,另一个是clang-12,编译时使用的是clang10,所以没有__builtin_preserve_type_info的定义。

使用如下命令切换clang的版本:

sudo update-alternatives  --install /usr/bin/clang clang /usr/bin/clang-12 100 --slave  /usr/bin/clang++ clang++ /usr/bin/clang++-12

编译成功,运行其中一个工具试一下,发现如下错误:

libbpf: failed to find valid kernel BTF
libbpf: Error loading vmlinux BTF: -3
libbpf: failed to load object 'wakeuptime_bpf'
libbpf: failed to load BPF skeleton 'wakeuptime_bpf': -3
failed to load BPF object: -3

这个是由于当前的内核在编译的时候没有支持BTF,所以需要重新配置和编译内核:

make menuconfig
选中kernel hacking --> Compile-time checks and compiler option -->Generate BTF typeinfo后,打开了编译开关CONFIG_DEBUG_INFO_BTF。

然后重新编译内核,又遇到了问题:

LD      .tmp_vmlinux.btfBTF     .btf.vmlinux.bin.o
KilledLD      .tmp_vmlinux.kallsyms1KSYMS   .tmp_vmlinux.kallsyms1.SAS      .tmp_vmlinux.kallsyms1.SLD      .tmp_vmlinux.kallsyms2KSYMS   .tmp_vmlinux.kallsyms2.SAS      .tmp_vmlinux.kallsyms2.SLD      vmlinuxBTFIDS  vmlinux
FAILED: load BTF from vmlinux: No such file or directory
make: *** [Makefile:1169:vmlinux] 错误 255
make: *** 正在删除文件“vmlinux”

不能正常的生成带有BTF信息的内核,这个问题困扰了我很久,百度也查询不到,后来我使用bing,查到了一些信息,生成BTF信息所使用的工具pahole有可能在使用中出了一些故障,我通过命令“dmesg|grep pahole”查了一下,发现它被oom killer杀掉了,而且根据dmesg信息,pahole确实消耗了很多的物理内存。

我关掉了一些正在使用的应用,重新编译,通过。

或者也可以使用如下命令,在编译内核时出现信息“BTF     .btf.vmlinux.bin.o”的时候,用如下命令提高pahole的oom score。

sudo su
ps -aux|grep pahole
echo -17 >/proc/pahole_pid/oom_adj

最后终于编译成功了,安装,重启,使用新的内核再运行一下libbpf-tools中的工具:

sudo ./softirqs
[sudo] kylin 的密码:
Tracing soft irq event time... Hit Ctrl-C to end.^C
SOFTIRQ          TOTAL_usecs
hi                       505
timer                   4425
net_rx                  1021
tasklet                   36
sched                  18034
rcu                     3407

成功。

libbpf-tools编译和使用步骤相关推荐

  1. VS2013中编译openssl的步骤和使用设置

    VS2013中编译openssl的步骤和使用设置 一.VS2013中编译openssl的步骤 版本号:openssl-1.0.1e 1.下载 OpenSSL http://www.openssl.or ...

  2. linux新建好文件后怎么编译,使用autoconf生成Makefile并编译工程的步骤

    前言 在Linux下,编译和链接需要用Makefile,而写好一个Makefile可不容易,写出一个规范的Makefile更是麻烦.我们可以利用autoconf来生成一个Makefile,尤其在大型工 ...

  3. Atlas 2.2.0源码编译及安装步骤

    Atlas 2.2.0源码编译及安装步骤 一.源码编译 1. 下载源码 2. 前置环境安装 3. 修改版本号 4. 修改源码中 atlas与kafka版本兼容问题 5. 开始编译 6. 问题锦集 二. ...

  4. 编译安装Nginx步骤详解

    编译安装Nginx步骤详解 1,去Nginx官方网站下载源码包并解压 curl -O 或wget 跟下载链接 tar -xf 解压 2,进入nginx解压后的目录执行./configure - ./c ...

  5. 虚拟打印机开发日志(一):使用x64 WIN7编译环境编译的完整步骤

    使用MS提供的MSPLOT驱动源文件,可方便地进行自用的打印机驱动开发或虚拟打印机驱动的开发,以下是一个最简的完整的使用DDK编译MSPLOT打印驱动的步骤: 1.编译对应的工具(64bit驱动) 打 ...

  6. moses 编译_Moses 训练步骤

    参考链接:http://www.statmt.org/moses/?n=Moses.Baseline 1.语料预处理 针对源和目标语言的语料库.有三步: 分词--> 大小写格式转换 --> ...

  7. mysql5.5在windows7下编译的详细步骤_Windows7下编译MySQL5.5的详细步骤

    由于在window7下编译MySQL5.5.19过程中遇到很多问题,所以再次把详细步骤写出来,以供大家参阅,这个是完整通过实验的步骤,网上一堆的东西不是少这个就是少那个,所以整理了下,希望帮助大家更好 ...

  8. httpd-2.4编译安装基本步骤

    Httpd-2.4 1.mpm支持运行dos机制 2.支持event mpm 3.支持异步读写 4.支持每模块及每个目录分别使用各自的日志级别: 5.每请求配置: 6.增强版的表达式分析 7.支持毫秒 ...

  9. 学习并整理windows下编译nginx的步骤

    参考链接:https://blog.csdn.net/i348018533/article/details/51701865 https://blog.csdn.net/hyhnoproblem/ar ...

最新文章

  1. word vba高效排版范例应用_Word 排版指北丨高效律师
  2. java代码示例(6-3)
  3. python数据表_第1关:了解python数据表操作
  4. C# 截取图片的方法
  5. 论java中可变参数
  6. 【完美】SpringBoot中使用注解来实现 Redis 分布式锁
  7. Mysql 远程自动化备份
  8. 为PHP开发搭建环境
  9. dede WAP 版 限制标题title的字数的方法
  10. 计算机机房无尘,计算机机房建设标准
  11. python离线语音识别_python语音识别模块
  12. java 多边形裁剪_使用 mesh 实现多边形裁剪图片!Cocos Creator!
  13. 修复steam服务器失败怎么办,steam服务器失败
  14. STM32——滴答定时器设置1us问题
  15. contextcapture多区块点云_Smart 3D (ContextCapture) 4.4.6版本最新功能
  16. 性能优化的终极目标-内存简析
  17. 信息隐藏——扩频水印
  18. 解决页面favicon.ico文件不存在提示404问题
  19. 国内移动应用数据安全发展现状
  20. 软考中级网络工程师知识点

热门文章

  1. linux中解压rar文件处理
  2. 大数据测试指标(一)
  3. C语言 编写函数求n个整数的和
  4. html中a标签的属性
  5. 手机App分发加速是如何实现的app分发有什么重要作用?cdn资源分配方式是如何分配的?
  6. 元宇宙中的虚拟办公室SkyOffice
  7. 人体行为识别研究综述
  8. 懒羊羊吃青草:懒羊羊是一只非常能吃的羊,它在青青草原上发现一块巨大的正方形草地,但灰太狼已经抢先一步在草地上布下了若干陷阱。正方形草地位于直角坐标系中...
  9. 1~n中与n互质数的个数(欧拉函数)
  10. Java 数据类型(基本数据类型、引用数据类型)