系统环境:
# uname -r
3.10.0-1160.99.1.el7.x86_64
# cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
1. gcc版本升级
代码语言:c复制#sudo yum install centos-release-scl -y
#sudo yum install devtoolset-7 -y
#sudo yum install devtoolset-8 -y
安装的是 devtoolset-7 和 devtoolset-8, 安装完成后全部文件在/opt/rh目录下:
代码语言:c复制# ls /opt/rh/
devtoolset-7 devtoolset-8
在所登录的会话生效高版本gcc:
代码语言:c复制# gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
# source /opt/rh/devtoolset-8/enable
# gcc --version
gcc (GCC) 8.3.1 20190311 (Red Hat 8.3.1-3)
添加到登录自启动脚本,避免每次登录需要手工执行source /opt/rh/devtoolset-8/enable
echo "source /opt/rh/devtoolset-8/enable" >> ~/.bash_profile
2. cmake升级
代码语言:c复制#wget https://github.com/Kitware/CMake/releases/download/v3.20.0/cmake-3.20.0.tar.gz
#tar -zxvf cmake-3.20.0.tar.gz
#source /opt/rh/devtoolset-8/enable
#cd cmake-3.20.0
#./bootstrap
#make
#make install
重新登录新的会话查看cmake版本:
#cmake --version
cmake version 3.20.0
3. llvm升级:
代码语言:c复制
#git clone https://github.com/llvm/llvm-project.git
#cd llvm-project
#mkdir llvm-build
#cd llvm-build
#source /opt/rh/devtoolset-8/enable
#cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" -G "Unix Makefiles" ../llvm
#make
#make install
4. 编译bcc以及libbpf-tools
代码语言:c复制编译bcc的过程会自动下载编译依赖的libbpf和bpftool,因此可以不需要再单独下载编译libbpf和bpftool
#git clone https://github.com/iovisor/bcc.git
#mkdir bcc/build; cd bcc/build
#cmake ..
#make
#cd ../libbpf-tools/
#make
编译通过后执行bcc中自带的libbpf的工具比如opensnoop会报错,这个是因为bcc.git提供的libbpf-tools工具集实现时使用了BTF相关接口,依赖内核开启CONFIG_DEBUG_INFO_BTF。
代码语言:c复制# ./opensnoop
libbpf: failed to find valid kernel BTF
failed to fetch necessary BTF for CO-RE: Operation not supported
5. 写一个不依赖BTF的ebpf测试程序验证centos7运行ebpf程序
代码语言:c复制
# cat trace_kfree_skb.bpf.c //内核态执行的bpf代码
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
struct args_kfree_skb {
void *regs;
void *skbaddr;
void *location;
unsigned short protocol;
};
SEC("tracepoint/skb/kfree_skb")
int tp_kfree_skb(struct args_kfree_skb *args)
{
__u32 pid = 0;
pid = bpf_get_current_pid_tgid();
bpf_printk("pid:%d,hello test bpf :skbaddr:%llx,location:%llxn", pid,args->skbaddr,args->location);
return 1;//perf trace -e skb:kfree_skb cannot get any message if here return 0. see kernel function perf_trace_run_bpf_submit()
}
char LICENSE[] SEC("license") = "GPL";
# cat trace_kfree_skb.c //用户态执行的bpf代码
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
#include "trace_kfree_skb.skel.h"
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
return vfprintf(stderr, format, args);
}
int main(int argc, char **argv)
{
struct trace_kfree_skb_bpf *skel;
int err;
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
if (setrlimit(RLIMIT_MEMLOCK, &r)) {
perror("setrlimit(RLIMIT_MEMLOCK)");
return 1;
}
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
/* Set up libbpf errors and debug info callback */
libbpf_set_print(libbpf_print_fn);
/* Open BPF application */
skel = trace_kfree_skb_bpf__open();
if (!skel) {
fprintf(stderr, "Failed to open BPF skeletonn");
return 1;
}
/* Load & verify BPF programs */
err = trace_kfree_skb_bpf__load(skel);
if (err) {
fprintf(stderr, "Failed to load and verify BPF skeletonn");
goto cleanup;
}
/* Attach tracepoint handler */
err = trace_kfree_skb_bpf__attach(skel);
if (err) {
fprintf(stderr, "Failed to attach BPF skeletonn");
goto cleanup;
}
printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` or run 'bpftool prog tracelog'"
"to see output of the BPF programs.n");
for (;;) {
sleep(60);
}
cleanup:
trace_kfree_skb_bpf__destroy(skel);
return 0;
}
#修改Makefile添加新增的测试代码:
bcc/libbpf-tools目录下的Makefile文件在APPS = 位置添加新的ebpf工具trace_kfree_skb:
APPS =
bashreadline
......
......
wakeuptime
trace_kfree_skb
$(BZ_APPS)
#
#执行make编译生成可执行文件trace_kfree_skb
# make
which: no cargo in (/opt/rh/devtoolset-8/root/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)
BPF trace_kfree_skb.bpf.o
GEN-SKEL trace_kfree_skb.skel.h
CC trace_kfree_skb.o
BINARY trace_kfree_skb
# ls trace_kfree_skb
trace_kfree_skb
编译bcc的过程会自动下载编译依赖的libbpf和bpftool,因此可以不需要再单独下载编译libbpf和bpftool,
如果验证程序不是放在bcc/libbpf里一起编译,则需要再单独下载编译安装libbpf和bpftool。
验证在centos7 3.10内核正常运行ebpf程序
# uname -r
3.10.0-1160.99.1.el7.x86_64
# cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core)
# ./trace_kfree_skb
libbpf: loading object 'trace_kfree_skb_bpf' from buffer
libbpf: elf: section(3) tracepoint/skb/kfree_skb, size 88, link 0, flags 6, type=1
libbpf: sec 'tracepoint/skb/kfree_skb': found program 'tp_kfree_skb' at insn offset 0 (0 bytes), code size 11 insns (88 bytes)
libbpf: elf: section(4) .reltracepoint/skb/kfree_skb, size 16, link 12, flags 40, type=9
libbpf: elf: section(5) .rodata, size 51, link 0, flags 2, type=1
libbpf: elf: section(6) license, size 4, link 0, flags 3, type=1
libbpf: license of trace_kfree_skb_bpf is GPL
libbpf: elf: section(7) .BTF, size 906, link 0, flags 0, type=1
libbpf: elf: section(9) .BTF.ext, size 128, link 0, flags 0, type=1
libbpf: elf: section(12) .symtab, size 144, link 1, flags 0, type=2
libbpf: looking for externs among 6 symbols...
libbpf: collected 0 externs total
libbpf: map 'trace_kf.rodata' (global data): at sec_idx 5, offset 0, flags 80.
libbpf: map 0 is "trace_kf.rodata"
libbpf: sec '.reltracepoint/skb/kfree_skb': collecting relocation for section(3) 'tracepoint/skb/kfree_skb'
libbpf: sec '.reltracepoint/skb/kfree_skb': relo #0: insn #4 against '.rodata'
libbpf: prog 'tp_kfree_skb': found data map 0 (trace_kf.rodata, sec 5, off 0) for insn 4
libbpf: map 'trace_kf.rodata': created successfully, fd=4
Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` or run 'bpftool prog tracelog'to see output of the BPF programs.
#新开一个会话执行cat /sys/kernel/debug/tracing/trace_pipe查看测试程序正常运行
参考:
https://bitsanddragons.wordpress.com/2022/09/19/error-cmake-3-1-or-higher-is-required-you-are-running-version-on-centos-7-x/
https://blog.csdn.net/yilun/article/details/126588552