ebpf程序开发(一)--ubuntu20.04

目录

[1 生成vmlinux.h文件](#1 生成vmlinux.h文件)

[2 编写bpf程序并编译](#2 编写bpf程序并编译)

[3 编译c程序](#3 编译c程序)

[4 运行程序](#4 运行程序)

[4.1 启动](#4.1 启动)

[4.2 观察ebpf的监视行为](#4.2 观察ebpf的监视行为)

[4.3 退出](#4.3 退出)

[4.4 卸载](#4.4 卸载)

[5 解释](#5 解释)


此实例作用是监视命令行输入,实时打印命令行执行的指令。

1 生成vmlinux.h文件

新建一个名为hello的文件夹。进入这个文件夹,然后命令行输入:

bash 复制代码
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h

下一步你将看到,bpf代码的编译需要这个头文件。

2 编写bpf程序并编译

在hello文件夹里建立hello.bpf.c文件:

cpp 复制代码
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

char _license[] SEC("license") = "GPL";
SEC("tracepoint/syscalls/sys_enter_execve")

int handle_execve(struct trace_event_raw_sys_enter *ctx)
{
    char comm[128] = {0};
    long res = bpf_probe_read_user_str(comm, sizeof(comm), (const char *)ctx->args[0]);
    if(res > 0)
    {
        bpf_printk("executed %s\n", comm);
    }
    return 0;
}

然后编译:

bash 复制代码
clang -target bpf -fno-unique-section-names -O2 -g -c hello.bpf.c -o hello.bpf.o

3 编译c程序

在hello文件夹里再建立一个hello.c文件:

cpp 复制代码
// hello.c
#include <stdio.h>
#include <unistd.h>
#include <bpf/libbpf.h>
#include <bpf/bpf.h>

int main(int argc, char **argv)
{
    struct bpf_object *obj;
    struct bpf_program *prog;
    struct bpf_link *link;
    int err;

    // 1. 打开编译好的 BPF 目标文件
    obj = bpf_object__open_file("hello.bpf.o", NULL);
    if (!obj) {
        fprintf(stderr, "Failed to open BPF object\n");
        return 1;
    }

    // 2. 将 BPF 程序加载到内核
    err = bpf_object__load(obj);
    if (err) {
        fprintf(stderr, "Failed to load BPF object: %d\n", err);
        bpf_object__close(obj);
        return 1;
    }

    // 3. 寻找我们在 BPF 代码中定义的 SEC("tracepoint/syscalls/sys_enter_execve") 程序
    prog = bpf_object__find_program_by_name(obj, "handle_execve");
    if (!prog) {
        fprintf(stderr, "Failed to find BPF program\n");
        bpf_object__close(obj);
        return 1;
    }

    // 4. 将程序挂载(Attach)到 tracepoint 上
    // 参数:程序指针, 挂载类型, 挂载点配置(这里自动从 SEC 名字解析)
    link = bpf_program__attach(prog);
    if (!link) {
        fprintf(stderr, "Failed to attach BPF program\n");
        bpf_object__close(obj);
        return 1;
    }

    printf("BPF Hello World program loaded and attached successfully!\n");
    printf("Open another terminal and run: sudo cat /sys/kernel/debug/tracing/trace_pipe\n");
    printf("Press Ctrl+C to exit.\n");

    // 5. 保持程序运行,等待事件触发
    while (1) {
        sleep(1);
    }

    // 6. 清理资源(正常情况不会执行到这里,被 Ctrl+C 打断)
    bpf_link__destroy(link);
    bpf_object__close(obj);

    return 0;
}

这里注意,上面语句

cpp 复制代码
    prog = bpf_object__find_program_by_name(obj, "handle_execve");

里面提到的handle_execve应该对应hello.bpf.c里的函数名。

然后编译:

bash 复制代码
gcc hello.c -o hello -lbpf -lelf -lz

4 运行程序

4.1 启动

bash 复制代码
sudo ./hello

4.2 观察ebpf的监视行为

打开一个新命令行,然后输入:

bash 复制代码
sudo cat /sys/kernel/debug/tracing/trace_pipe

然后再打开一个命令行,输入一个常见指令,比如cat和ls,再观察trace_pipe的打印:

4.3 退出

ctrl+C退出

4.4 卸载

输入:

bash 复制代码
sudo bpftool prog show

假如上面的命令输出仍然含有"hello"字样,说明它还在内存里。使用如下命令删除它:

bash 复制代码
sudo rm -rf /sys/fs/bpf/hello

5 解释

这里最关键的是bpf程序里

cpp 复制代码
bpf_probe_read_user_str

一句。这一句获取了命令行输入的命令。

相关推荐
‎ദ്ദിᵔ.˛.ᵔ₎1 小时前
Linux 线程控制
linux
叼烟扛炮1 小时前
Linux 学习笔记(八):GCC 编译器的四大阶段与链接原理
linux·笔记·学习
运维踩坑日记1 小时前
【无标题】
linux·运维·windows
虚无的纽扣2 小时前
【Linux】线程(下):怎么创建、终止与分离一个线程
linux·运维·服务器
叼烟扛炮2 小时前
Linux 学习笔记(七):软件安装与 Vim 编辑器极速入门
linux·学习·编辑器
金色熊族2 小时前
在Qt中使用asan检测内存泄漏(二)--检查依赖库的内存使用
linux·qt·asan
叼烟扛炮2 小时前
Linux 学习笔记(十六):进程的调度与优先级——谁先抢到 CPU?
linux·笔记·学习
幽灵诶2 小时前
学习Linux
linux·学习
kyle~2 小时前
Linux --- CPU 调度机制
linux·运维·数码相机