一、bcc 工具
bcc 的全称:BPF Compiler Collection
BCC(BPF Compiler Collection)是一个用于创建高效的内核跟踪和操作程序的工具包,包含了几个有用的工具和示例。它利用了扩展的BPF(Berkeley Packet Filters),即eBPF,这是一个最早添加到Linux 3.15的新特性。大部分BCC所使用的功能要求Linux 4.1及以上版本。
eBPF被Ingo Molnár描述为:
在这个周期内更有趣的特性之一是能够将eBPF程序(用户定义的、在内核中执行的沙箱化的字节码)附加到kprobes上。这允许对实时内核镜像进行用户定义的仪表化,这些程序永远不会崩溃、挂起或对内核产生负面影响。
BCC使得编写BPF程序更加容易,它使用C语言编写内核仪表化程序(并在LLVM周围包含了一个C语言包装器),并提供了Python和lua的前端。它适用于许多任务,包括性能分析和网络流量控制。
二、bcc 编译
bcc 源码路径:
GitHub - iovisor/bcc: BCC - Tools for BPFhttps://github.com/iovisor/bcc/tree/master
2.1 内核配置选项的打开:
In general, to use these features, a Linux kernel version 4.1 or newer is required. In addition, the kernel should have been compiled with the following flags set:
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
There are a few optional kernel flags needed for running bcc networking examples on vanilla kernel:
CONFIG_NET_SCH_SFQ=m
CONFIG_NET_ACT_POLICE=m
CONFIG_NET_ACT_GACT=m
CONFIG_DUMMY=m
CONFIG_VXLAN=m
Kernel compile flags can usually be checked by looking at /proc/config.gz
or /boot/config-<kernel-version>
.
上面的内核配置选项都是github上官方给出的配置选项,但是在使用bcc过程中,会遇到一些问题,需要增加打开内核的选项,如下所示:
1、执行 execsnoop 时,报错:
解决办法:
打开内核选项:CONFIG_DEBUG_INFO_BTF=y
BTF是什么?
BTF 是 Linux 内核中的一种功能,全称为 BPF Type Format。BTF 最初是为 eBPF(扩展 Berkeley Packet Filter)引入的,但它在内核中的使用已经远远超出了 eBPF 的范畴。
BTF 的主要功能是提供一种将内核数据结构描述导出到用户空间的方法,以便用户空间的程序(如调试器、静态分析工具等)能够了解内核数据结构的布局和语义。具体来说,BTF 提供了以下功能:
-
类型信息: BTF 包含了内核数据结构的类型信息,如结构体、联合体、枚举类型等,以及它们的成员和类型信息。
-
函数信息: BTF 还包含了内核函数的信息,如参数类型、返回类型等。
-
源代码位置信息: BTF 还可以包含源代码位置信息,以帮助调试器等工具定位内核代码中的位置。
BTF 的引入使得用户空间的工具能够更好地理解内核数据结构,从而实现更高效的调试、性能分析和安全分析等功能。例如,调试器可以使用 BTF 来显示内核中的变量和数据结构,静态分析工具可以使用 BTF 来检查内核中的代码逻辑,而不必依赖于手动编写解析内核数据结构的代码。
总的来说,BTF 是 Linux 内核中的一种功能,用于将内核数据结构描述导出到用户空间,以帮助用户空间的工具更好地理解和分析内核代码。
----接着打开选项后,又遇到编译 的问题,如下:
FAILED:load BTF from vmlinux:
解决办法:
下载 pahole 的包,可以解决;但是下载的包版本不对,还是会报这个错误。
我遇到的问题是:安装 pahole-1.25 版本,还是报上面的错误,安装pahole-1.22-8,得以解决;
百度了一下 pahole-1.25版本的解决办法,使用之后没有解决,不知道什么原因。
下面先写出网友的解决办法:
diff --git a/scripts/pahole-flags.sh b/scripts/pahole-flags.sh
> index 0d99ef17e4a528..1f1f1d397c399a 100755
> --- a/scripts/pahole-flags.sh
> +++ b/scripts/pahole-flags.sh
> @@ -19,5 +19,9 @@ fi
> if [ "${pahole_ver}" -ge "122" ]; then
> extra_paholeopt="${extra_paholeopt} -j"
> fi
> +if [ "${pahole_ver}" -ge "124" ]; then
> + # see PAHOLE_HAS_LANG_EXCLUDE
> + extra_paholeopt="${extra_paholeopt} --skip_encoding_btf_enum64"
> +fi
>
> echo ${extra_paholeopt}
>
上面的pahole-flags.sh 文件也只是存在内核5.15版本以上吧,具体没有去核实,只是我的内核5.10 的版本里面没有上面的pahole-flags.sh 脚本。但是,有./scripts/link-vmlinux.sh
增加修改后的link-vmlinux.sh,但是没有解决这个问题,只是用于展示解决问题的过程。
去查看内核5.15 的pahole-flags.sh 脚本,内容如下:
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
extra_paholeopt=
if ! [ -x "$(command -v ${PAHOLE})" ]; then
exit
fi
pahole_ver=$($(dirname $0)/pahole-version.sh ${PAHOLE})
if [ "${pahole_ver}" -ge "118" ] && [ "${pahole_ver}" -le "121" ]; then
# pahole 1.18 through 1.21 can't handle zero-sized per-CPU vars
extra_paholeopt="${extra_paholeopt} --skip_encoding_btf_vars"
fi
if [ "${pahole_ver}" -ge "121" ]; then
extra_paholeopt="${extra_paholeopt} --btf_gen_floats"
fi
if [ "${pahole_ver}" -ge "124" ]; then
extra_paholeopt="${extra_paholeopt} --skip_encoding_btf_enum64"
fi
echo ${extra_paholeopt}
~
看内容 ,内核版本越高,pahole高版本带来的问题也就解决了。
2、执行 cachestat 1 3 ,报错:
解决办法:
打开内核的debug_fs 的功能,重新编译然后烧录内核。
系统起来后,确保:mount -t debugfs debugfs /sys/kernel/debug
2.2 Repositories
/etc/apt/sources.list
should include the non-free
repository and look something like this:
deb http://deb.debian.org/debian sid main contrib non-free
deb-src http://deb.debian.org/debian sid main contrib non-free
2.3 Install Build Dependencies
# Before you begin
apt-get update
# According to https://packages.debian.org/source/sid/bpfcc,
# BCC build dependencies:
sudo apt-get install arping bison cmake dh-python \
dpkg-dev pkg-kde-tools ethtool flex inetutils-ping iperf \
libbpf-dev libedit-dev libelf-dev \
libfl-dev libzip-dev linux-libc-dev libluajit-5.1-dev \
luajit python3-netaddr python3-pyroute2 python3-setuptools python3
注意:llvm 和clang 不能下载 10版本,否则编译不过。需要下载 12版本。
sudo apt install -y build-essential cmake flex \
libllvm12 llvm-12-dev libclang-12-dev zlib1g-dev \
liblzma-dev netperf iperf
netperf 是安装不了的,需要单独下载 源码编译安装。如果不安装,也是可以编译过的,可能会有一些功能使用不了。如果到时需要,在下载安装重新编译。
版本要求:
- LLVM 3.7.1 or newer, compiled with BPF support (default=on)
- Clang, built from the same tree as LLVM
- cmake (>=3.1), gcc (>=4.7), flex, bison
- LuaJIT, if you want Lua support
- Optional tools used in some examples: arping, netperf, and iperf
2.4 确保默认的python版本是3:
whereis python3
#python3: /usr/bin/python3
设置Python的默认为python3
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 100
#update-alternatives: using /usr/bin/python3 to provide /usr/bin/python (python) in auto mode
2.5 Install and compile 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
make install 安装的 路径:/usr/share/bcc/
也可以手动修改安装路径:
cmake .. -DCMAKE_INSTALL_PREFIX=/usr (路径自定义)
如果使用默认,可以把路径添加到$PATH中,
bcctools=/usr/share/bcc/tools
bccexamples=/usr/share/bcc/examples
export PATH=$bcctools:$bccexamples:$PATH
三、bcc 工具的使用
3.1 bitesize
数据抓取成功。
3.2 cachestat 1 3
因为内核没有打开debugfs ,所以会报错:
需要打开内核debugfs,并挂载debugfs
mount -t debugfs debugfs /sys/kernel/debug
解决之后: