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

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

相关推荐
StarsGreen1 小时前
libva在intel平台上的前端流程简介
linux
坤坤子吖4 小时前
Linux网络编程:自定义应用层协议与 JSON 序列化
linux·服务器·网络·c++·笔记·json
Felven5 小时前
华为鲲鹏920s芯片serdestool工具使用说明
linux·运维·服务器·华为·鲲鹏920·serdestool
莫晓燚6 小时前
mall 电商项目完整部署---实战
linux·运维·docker·容器
咋的啥名都用不了呢~6 小时前
Linux项目部署5(安装Nginx的插件)
linux
CodeYp20196 小时前
第11讲:应用层协议 HTTP
linux·http
爱和冰阔落6 小时前
【Linux网络】JsonCpp 怎么实现序列化?从 Request/Response 到网络计算器消息设计
linux·运维·网络·php
我是koten12 小时前
【运维杂谈】K8s遇到Terminating的名称空间删除不了怎么办?(解决方案亲测有效)
linux·运维·服务器·云原生·kubernetes·k8s·名称空间
2601_9679873720 小时前
安装 Redis 或 Redis Stack
linux·windows·redis·macos·安装
feng_you_ying_li20 小时前
linux之数据链路层
linux·网络·智能路由器