libbpf-tools编译和使用步骤

之前尝试了两种方法使用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.git

mkdir 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.py

Tracing block device I/O... Hit Ctrl-C to end.

^C
     usecs               : count     distribution
         0 -> 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.btf
  BTF     .btf.vmlinux.bin.o
Killed
  LD      .tmp_vmlinux.kallsyms1
  KSYMS   .tmp_vmlinux.kallsyms1.S
  AS      .tmp_vmlinux.kallsyms1.S
  LD      .tmp_vmlinux.kallsyms2
  KSYMS   .tmp_vmlinux.kallsyms2.S
  AS      .tmp_vmlinux.kallsyms2.S
  LD      vmlinux
  BTFIDS  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

成功。

  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
platform-tools_r31.0.3-windows.zip platform-tools是很多刷机的朋友都会用到的工具包,Android SDK其中的platform-tools包可以对安卓设备进行调试,包括解锁、刷机等操作都可以使用这个工具包来进行,其中包含开发app的平台依赖的开发和调试工具,包括 adb、fastboot等,有需要的赶快下载吧!功能介绍platform-tools包含开发app的平台依赖的开发和调试工具,包括 adb、fastboot等android sdk里的各目录作用AVD Manager.exe:虚拟机管理工具,用于建立和管理虚拟机。SDK Manager.exe:sdk管理工具,用于管理、下载sdk、sdk工具,能及扩展工具tools目录:包括测试、调试、第三方工具。模拟器、数据管理工具等。build-tools目录:编译工具目录,包含了转化为davlik虚拟机的编译工具。包括aapt(Android Asset Packaging Tool):编译应用程序的资源文件(包括AndroidManifest.xml和你的Activities的xml文件),生成R.java文件,这样你就可以从你的java代码中引用资源。aidl:把.aidl 接口转换成java接口.dx:转化.class中间代码为dvlik中间代码,所有经过java编译的生成.class文件都需要此工具进行转换,最后打包进apk文件中.dexdump:dump devlik中间代码platform-tools目录:包含开发app的平台依赖的开发和调试工具。包括adb:android调试工具fastboot:boot工具platforms/目录:包括android的平台。包含在android.jar库中。你必须指一个平台为你的编译目标。system-images目录:编译好的系统映像。模拟器可以直接加载。sources目录:android sdk的源码目录samples目录:sdk例子

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值