libbpf 开发指南:将bpf结构固定到文件系统以便于进程共享

目录

将BPF 映射(maps)固定到指定的文件系统路径

函数原型与作用

代码demo

makefile

cmake

将BPF 程序固定到指定的文件系统路径

函数原型与解释

代码demo

makefile

cmake

将object固定到文件系统

函数原型与解析

代码demo

makefile

cmake


将BPF 映射(maps)固定到指定的文件系统路径

函数原型与作用

/*
    bpf_object__pin_maps() pins each map contained within the BPF object at the passed directory.

    If path is NULL bpf_map__pin (which is being used on each map) will use the pin_path attribute of each map. In this case, maps that don’t have a pin_path set will be ignored.

    Parameters:

            obj – Pointer to a valid BPF object

            path – A directory where maps should be pinned.

    Returns:

        0, on success; negative error code, otherwise


*/
LIBBPF_API int bpf_object__pin_maps (struct bpf_object *obj, const char *path)

bpf_object__pin_maps 函数的作用是将 BPF 对象中的所有 BPF 映射(maps)固定到指定的文件系统路径。固定(pinning)是一种将 BPF 映射的生命周期与创建它的进程解耦的方法。通过将映射固定到文件系统上的某个路径,其他进程可以在稍后访问和使用这些映射,即使创建它的原始进程已经退出。通常,BPF 映射会在创建它们的进程退出时自动关闭,但是固定映射允许它们在进程之间共享和持久化。

pf_object__unpin_maps 函数的作用是将 BPF 对象中的所有 BPF 映射(maps)从指定的文件系统路径解除固定。在之前使用 bpf_object__pin_maps 将映射固定到文件系统的路径后,你可以使用 bpf_object__unpin_maps 将它们解除固定。解除固定后,映射将不再在文件系统上可用。

代码demo

#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>

int main() {
    struct bpf_object *obj;
    const char *filename = "example.bpf.o";
    const char *pin_path = "/sys/fs/bpf/example_maps";
    int err;

    // 设置 RLIMIT_MEMLOCK 为无限制
    struct rlimit rlim = {RLIM_INFINITY, RLIM_INFINITY};
    if (setrlimit(RLIMIT_MEMLOCK, &rlim)) {
        perror("Failed to set RLIMIT_MEMLOCK");
        return 1;
    }

    // 使用 bpf_object__open_file 打开 BPF 对象文件
    obj = bpf_object__open_file(filename, NULL);
    if (libbpf_get_error(obj)) {
        fprintf(stderr, "Error loading BPF object from file: %s\n", filename);
        return 1;
    }

    // 使用 bpf_object__load 加载 BPF 对象到内核中
    err = bpf_object__load(obj);
    if (err) {
        fprintf(stderr, "Error loading BPF object: %d\n", err);
        bpf_object__close(obj);
        return 1;
    }

    printf("BPF object loaded successfully\n");

    // 使用 bpf_object__pin_maps 将 BPF 对象中的所有地图固定到指定路径
    err = bpf_object__pin_maps(obj, pin_path);
    if (err) {
        fprintf(stderr, "Error pinning BPF maps: %d\n", err);
        bpf_object__close(obj);
        return 1;
    }

    printf("BPF maps pinned at %s\n", pin_path);

    // 在此处,你可以执行其他操作,例如与固定的地图进行交互
    // 然后,在完成操作后,使用 bpf_object__unpin_maps 解除固定:
    err = bpf_object__unpin_maps(obj, pin_path);
    if (err) {
        fprintf(stderr, "Error unpinning BPF maps: %d\n", err);
        bpf_object__close(obj);
        return 1;
    }

    printf("BPF maps unpinned from %s\n", pin_path);

    bpf_object__close(obj);
    return 0;
}

makefile

CC = gcc
CFLAGS = -Wall -Wextra -O2

TARGET = example
SRCS = example.c

OBJS = $(SRCS:.c=.o)

all: $(TARGET)

$(TARGET): $(OBJS)
	$(CC) $(CFLAGS) -o $@ $^

%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

clean:
	rm -f $(OBJS) $(TARGET)

.PHONY: all clean

cmake

cmake_minimum_required(VERSION 3.10)

project(example LANGUAGES C)

set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -O2")

add_executable(example example.c)

将BPF 程序固定到指定的文件系统路径

函数原型与解释

LIBBPF_API int bpf_object__pin_programs (struct bpf_object *obj, const char *path)

LIBBPF_API int bpf_object__unpin_programs (struct bpf_object *obj, const char *path)

将 BPF 对象中的所有 BPF 程序(programs)固定到指定的文件系统路径。固定后,其他进程可以通过路径找到这些 BPF 程序并将它们附加到相应的事件(event)上。这有助于实现进程之间的 BPF 程序共享,以及在进程终止后 BPF 程序仍然能被其他进程使用。

bpf_object__unpin_programs代表解除固定

代码demo

#include <bpf/bpf_helpers.h>
#include <linux/bpf.h>

SEC("kprobe/__x64_sys_getpid")
int bpf_prog1(struct pt_regs *ctx) {
    char comm[16];
    bpf_get_current_comm(&comm, sizeof(comm));

    // 在此处,你可以使用获取到的 comm(进程名)执行其他操作

    return 0;
}

char _license[] SEC("license") = "GPL";
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>

int main() {
    struct bpf_object *obj;
    const char *filename = "example.bpf.o";
    const char *pin_path = "/sys/fs/bpf/example_programs";
    int err;

    // 设置 RLIMIT_MEMLOCK 为无限制
    struct rlimit rlim = {RLIM_INFINITY, RLIM_INFINITY};
    if (setrlimit(RLIMIT_MEMLOCK, &rlim)) {
        perror("Failed to set RLIMIT_MEMLOCK");
        return 1;
    }

    // 使用 bpf_object__open_file 打开 BPF 对象文件
    obj = bpf_object__open_file(filename, NULL);
    if (libbpf_get_error(obj)) {
        fprintf(stderr, "Error loading BPF object from file: %s\n", filename);
        return 1;
    }

    // 使用 bpf_object__load 加载 BPF 对象到内核中
    err = bpf_object__load(obj);
    if (err) {
        fprintf(stderr, "Error loading BPF object: %d\n", err);
        bpf_object__close(obj);
        return 1;
    }

    printf("BPF object loaded successfully\n");

    // 使用 bpf_object__pin_programs 将 BPF 对象中的所有程序固定到指定路径
    err = bpf_object__pin_programs(obj, pin_path);
    if (err) {
        fprintf(stderr, "Error pinning BPF programs: %d\n", err);
        bpf_object__close(obj);
        return 1;
    }

    printf("BPF programs pinned at %s\n", pin_path);

    // 在此处,你可以执行其他操作,例如将固定的程序附加到事件上

    bpf_object__close(obj);
    return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/resource.h>
#include <sys/syscall.h>
#include <linux/perf_event.h>
#include <bpf/libbpf.h>

static int perf_event_open_tracepoint(const char *name, const char *prog_path) {
    int err;
    struct bpf_program *prog;
    struct bpf_object *obj;

    // 打开固定的 BPF 程序
    obj = bpf_object__open(prog_path);
    if (libbpf_get_error(obj)) {
        fprintf(stderr, "Error opening BPF object: %d\n", libbpf_get_error(obj));
        return -1;
    }

    prog = bpf_program__next(NULL, obj);
    if (!prog) {
        fprintf(stderr, "Error finding BPF program\n");
        bpf_object__close(obj);
        return -1;
    }

    // 使用 perf_event_open 系统调用创建 perf event
    struct perf_event_attr attr = {
        .type = PERF_TYPE_TRACEPOINT,
        .size = sizeof(attr),
        .config = bpf_program__kprobe_prog_type(prog),
        .sample_period = 1,
        .sample_type = PERF_SAMPLE_RAW,
        .wakeup_events = 1,
    };

    err = syscall(__NR_perf_event_open, &attr, -1, 0, -1, 0);
    if (err < 0) {
        perror("Error creating perf event");
        bpf_object__close(obj);
        return -1;
    }

    int perf_event_fd = err;

    // 将 BPF 程序附加到 perf event
    err = bpf_prog_attach(bpf_program__fd(prog), perf_event_fd, 0, 0);
    if (err) {
        fprintf(stderr, "Error attaching BPF program: %d\n", err);
        close(perf_event_fd);
        bpf_object__close(obj);
        return -1;
    }

    printf("Successfully attached BPF program to perf event\n");

    return perf_event_fd;
}

int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <tracepoint_name> <pinned_prog_path>\n", argv[0]);
        return 1;
    }

    const char *tracepoint_name = argv[1];
    const char *pinned_prog_path = argv[2];

    int perf_event_fd = perf_event_open_tracepoint(tracepoint_name, pinned_prog_path);
    if (perf_event_fd < 0) {
        return 1;
    }

    printf("Press Ctrl+C to exit\n");
    pause(); // Wait for signals

    // Clean up
    close(perf_event_fd);

    return 0;
}

makefile

CC = gcc
CLANG = clang
CFLAGS = -Wall -I/usr/include/bpf
LDFLAGS = -lbpf

BPF_TARGET = prog.o
BPF_SRC = prog.c

PIN_TARGET = pin_programs
PIN_SRC = pin_programs.c

ATTACH_TARGET = attach_pinned_program
ATTACH_SRC = attach_pinned_program.c

all: $(BPF_TARGET) $(PIN_TARGET) $(ATTACH_TARGET)

$(BPF_TARGET): $(BPF_SRC)
	$(CLANG) -O2 -target bpf -c $(BPF_SRC) -o $(BPF_TARGET)

$(PIN_TARGET): $(PIN_SRC)
	$(CC) $(CFLAGS) $(PIN_SRC) -o $(PIN_TARGET) $(LDFLAGS)

$(ATTACH_TARGET): $(ATTACH_SRC)
	$(CC) $(CFLAGS) $(ATTACH_SRC) -o $(ATTACH_TARGET) $(LDFLAGS)

clean:
	rm -f $(BPF_TARGET) $(PIN_TARGET) $(ATTACH_TARGET)

.PHONY: all clean

cmake

cmake_minimum_required(VERSION 3.10)
project(bpf_example)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")

find_library(LIBBPF libbpf.so REQUIRED)

add_executable(pin_programs pin_programs.c)
target_link_libraries(pin_programs ${LIBBPF})
target_include_directories(pin_programs PUBLIC /usr/include/bpf)

add_custom_command(
    OUTPUT prog.o
    COMMAND clang -O2 -target bpf -c ${CMAKE_CURRENT_SOURCE_DIR}/prog.c -o prog.o
    DEPENDS prog.c
    VERBATIM
)

add_custom_target(
    prog_bpf
    DEPENDS prog.o
)

add_executable(attach_pinned_program attach_pinned_program.c)
target_link_libraries(attach_pinned_program ${LIBBPF})
target_include_directories(attach_pinned_program PUBLIC /usr/include/bpf)

将object固定到文件系统

函数原型与解析

LIBBPF_API int bpf_object__pin(struct bpf_object *object, const char *path);

参数解释:

  • object:要固定的 bpf_object 实例。
  • path:文件系统中的路径,用于保存固定的 BPF 对象。通常,这将是在 /sys/fs/bpf 目录下的一个路径。

返回值:

  • 成功时返回 0。
  • 失败时返回负数错误代码。

代码demo

#include <bpf/bpf_helpers.h>
#include <linux/bpf.h>

SEC("kprobe/__x64_sys_getpid")
int bpf_prog1(struct pt_regs *ctx) {
    return 0;
}

char _license[] SEC("license") = "GPL";
#include <stdio.h>
#include <stdlib.h>
#include <bpf/libbpf.h>

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <path_to_pin>\n", argv[0]);
        return 1;
    }

    const char *path_to_pin = argv[1];

    struct bpf_object *bpf_obj;
    struct bpf_program *prog;

    // 加载 BPF 程序
    bpf_obj = bpf_object__open("prog.o");
    if (libbpf_get_error(bpf_obj)) {
        fprintf(stderr, "Error opening BPF object: %d\n", libbpf_get_error(bpf_obj));
        return 1;
    }

    // 设置 BPF 程序的类型
    bpf_object__for_each_program(prog, bpf_obj) {
        bpf_program__set_type(prog, BPF_PROG_TYPE_KPROBE);
    }

    // 加载 BPF 对象
    int err = bpf_object__load(bpf_obj);
    if (err) {
        fprintf(stderr, "Error loading BPF object: %d\n", err);
        bpf_object__close(bpf_obj);
        return 1;
    }

    // 固定 BPF 对象
    err = bpf_object__pin(bpf_obj, path_to_pin);
    if (err) {
        fprintf(stderr, "Error pinning BPF object: %d\n", err);
        bpf_object__close(bpf_obj);
        return 1;
    }

    printf("Successfully pinned BPF object at: %s\n", path_to_pin);

    // 关闭 BPF 对象。请注意,在固定 BPF 对象后,它将继续存在,即使已关闭并释放相关资源。
    bpf_object__close(bpf_obj);

    return 0;
}
clang -O2 -target bpf -c prog.c -o prog.o
gcc -I/usr/include/bpf -o pin_bpf_prog pin_bpf_prog.c -lbpf
sudo mkdir -p /sys/fs/bpf/example_program
sudo ./pin_bpf_prog /sys/fs/bpf/example_program/prog1

makefile

CC = gcc
CLANG = clang
CFLAGS = -Wall -I/usr/include/bpf
LDFLAGS = -lbpf

BPF_TARGET = prog.o
BPF_SRC = prog.c

PIN_TARGET = pin_bpf_prog
PIN_SRC = pin_bpf_prog.c

all: $(BPF_TARGET) $(PIN_TARGET)

$(BPF_TARGET): $(BPF_SRC)
	$(CLANG) -O2 -target bpf -c $(BPF_SRC) -o $(BPF_TARGET)

$(PIN_TARGET): $(PIN_SRC)
	$(CC) $(CFLAGS) $(PIN_SRC) -o $(PIN_TARGET) $(LDFLAGS)

clean:
	rm -f $(BPF_TARGET) $(PIN_TARGET)

.PHONY: all clean

cmake

cmake_minimum_required(VERSION 3.10)
project(bpf_pin_example)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")

find_library(LIBBPF libbpf.so REQUIRED)

add_custom_command(
    OUTPUT prog.o
    COMMAND clang -O2 -target bpf -c ${CMAKE_CURRENT_SOURCE_DIR}/prog.c -o prog.o
    DEPENDS prog.c
    VERBATIM
)

add_custom_target(
    prog_bpf
    DEPENDS prog.o
)

add_executable(pin_bpf_prog pin_bpf_prog.c)
target_link_libraries(pin_bpf_prog ${LIBBPF})
target_include_directories(pin_bpf_prog PUBLIC /usr/include/bpf)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ym影子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值