簡體   English   中英

我在一個程序中有一個 function 調用,這個 function 已被貶值。有沒有更新的版本可以在我的代碼中使用? ebpf 中的 perf_buffer__new

[英]I have a function call in one program and this function is depreciated.Is there any newer version that I can use in my code | perf_buffer__new in ebpf

我有這個折舊的 function。 首先,如何找到折舊功能的新替代方案。 function 存在於 libbpf 庫中,而perf_buffer__new是確切的名稱。 所以基本上顧名思義,它用於創建性能緩沖區以在用戶空間和 kernel 之間共享信息。 首先,我想知道 perf 緩沖區是否僅特定於 ebpf 過濾器。 並不意味着我可以在任何東西中使用 perf 緩沖區。 例如,如果我有一些驅動程序代碼,那么我只需添加性能緩沖區以在某些用戶空間應用程序和驅動程序之間共享信息。 所以在 web 上進行了一些搜索,我發現它專門鏈接到 ebpf,這是真的嗎?

所以這是我的代碼,它使用調用perf_buffer__new但 function 已貶值,這個 function 在 libbpf 的 libbpf.h Z099FB995346F31C749F6E40EDB0

所以我喜歡新的我可以在我的代碼中使用的新替代方案,如果 api 發生變化,那么我想讓你知道我正在嘗試將 SEC("kprobe/__x64_sys_recvfrom") 中的緩沖區參數共享給用戶空間為此,我使用了 PT_REGS_PARM2 和 bpf_probe_read_kernel 並將參數包含在 map 數據中。 因此,如果 api 被更改,那么如何完成這是我的用戶空間和 ebpf 程序

用戶空間.c

    // SPDX-License-Identifier: GPL-2.0-only
#include <stdio.h>
#include <fcntl.h>
#include <poll.h>
#include <time.h>
#include <signal.h>
#include <bpf/libbpf.h>


//create .o file root@this:/home/ubuntu/Desktop/ebpf/kern# clang -I /lib/modules/5.14.1/build -I /usr/include/bpf/ -O2 -Wall -c trace_output_user.c

static __u64 time_get_ns(void)
{
    struct timespec ts;

    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec * 1000000000ull + ts.tv_nsec;
}

static __u64 start_time;
static __u64 cnt;

#define MAX_CNT 100000ll

static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size)
{
    struct {
        int pid;
        char cookie[90];
        char *buf;
        } *e = data;
        int i=0;
    printf("hello\n");
    
    printf(" _____________________________________________________%d \n________%s\n",e->pid,e->buf);
    i++;


    //printf("received map value = %s\n",e->cookie);
    /*if (e->cookie != 0x12345678) {
        printf("BUG pid %llx cookie %d sized %d\n",
               e->pid, e->cookie, size);
        return;
    }

    cnt++;

    if (cnt == MAX_CNT) {
        printf("recv %lld events per sec\n",
               MAX_CNT * 1000000000ll / (time_get_ns() - start_time));
        return;
    }*/
}

int main(int argc, char **argv)
{
    struct perf_buffer_opts pb_opts = {};
    struct bpf_link *link = NULL;
    struct bpf_program *prog;
    struct perf_buffer *pb;
    struct bpf_object *obj;
    int map_fd, ret = 0;
    char filename[256];
    FILE *f;

    //snprintf(filename, sizeof(filename), "..o", argv[0]);
    obj = bpf_object__open_file("./kprobe_send.o", NULL);
    if (libbpf_get_error(obj)) {
        fprintf(stderr, "ERROR: opening BPF object file failed\n");
        return 0;
    }

    /* load BPF program */
    if (bpf_object__load(obj)) {
        fprintf(stderr, "ERROR: loading BPF object file failed\n");
        goto cleanup;
    }

    map_fd = bpf_object__find_map_fd_by_name(obj, "my_map");
    if (map_fd < 0) {
        fprintf(stderr, "ERROR: finding a map in obj file failed\n");
        goto cleanup;
    }
    printf("before\n");
    prog = bpf_object__find_program_by_name(obj, "bpf_prog1");
    if (libbpf_get_error(prog)) {
        fprintf(stderr, "ERROR: finding a prog in obj file failed\n");
        goto cleanup;
    }
    printf("after\n");

    link = bpf_program__attach(prog);
        printf("after\n");
    if (libbpf_get_error(link)) {
        fprintf(stderr, "ERROR: bpf_program__attach failed\n");
        link = NULL;
        goto cleanup;
    }
    printf("after\n");
    pb_opts.sample_cb = print_bpf_output;
    pb = perf_buffer__new_deprecated(map_fd, 8, &pb_opts);//error
    printf("after\n");
    ret = libbpf_get_error(pb);
    if (ret) {
        printf("failed to setup perf_buffer: %d\n", ret);
        return 1;
    }

    f = popen("taskset 1 dd if=/dev/zero of=/dev/null", "r");
    (void) f;

    start_time = time_get_ns();
    while ((ret = perf_buffer__poll(pb, 1000)) >= 0 && cnt < MAX_CNT) {
    }
    kill(0, SIGINT);

cleanup:
    bpf_link__destroy(link);
    bpf_object__close(obj);
    return ret;
}

Kernel.c

#include <linux/ptrace.h>
#include <linux/version.h>
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <string.h>
#include <sys/sendfile.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include </usr/include/bpf/bpf_tracing.h>
#include <linux/seccomp.h>
#define RAND_MAX 0x7fff
#define PERF_SAMPLE_RAW  1U << 0
#define randrange(N) rand() / (RAND_MAX/(N) + 1)
#define MAX 100000000        /* Values will be in the range (1 .. MAX) */


struct {
    __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
    __uint(key_size, sizeof(int));
    __uint(value_size, sizeof(int));
    __uint(max_entries, 100);
} my_map SEC(".maps");

SEC("kprobe/__x64_sys_recvfrom")
int bpf_prog1(struct pt_regs *ctx)
{

    static int vektor[100000000];
    int candidates[MAX];
    int i;
    long key;

    //srand(time(NULL));   /* Seed the random number generator. */

    /*for (i=0; i<MAX; i++)
    candidates[i] = i;

    for (i = 0; i < MAX-1; i++) {
        int c = randrange(MAX-i);
        int t = candidates[i];
        candidates[i] = candidates[i+c];
        candidates[i+c] = t;
    
    }
    
    for (i=0; i<10; i++)
    vektor[i] = candidates[i] + 1;*/
    struct S {
        int pid;
        char cookie[90];
        char *ptr;
        
    } data={1,""};
        //char *ptr =   PT_REGS_PARM2(ctx);
        
        
        struct seccomp_data sd;

    bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx));
    if (sd.args[2] > 128 && sd.args[2] <= 1024) {
        char fmt[] = "read(fd=%d, buf=%p, size=%d)\n";
        bpf_trace_printk(fmt, sizeof(fmt),
                 sd.args[0], sd.args[1], sd.args[2]);
        data.ptr=(char *)sd.args[1];         
//      memcpy(data.ptr,sd.args[1],sizeof(char)*220);        
    }

        
        

    //data.pid =count;// bpf_get_current_pid_tgid();
    //if(buf==NULL)
    //memcpy(data.cookie,buf,20);
    //data.ptr=ptr; 
 //     data.cookie[0]=buf[0];
    //bpf_get_current_comm(&data.cookie, sizeof(data.cookie));
    
    //key=vektor[i];
    //bpf_map_update_elem(fd,&key,&data,BPF_ANY);
    //bpf_perf_event_output(ctx, &my_map, 1, &data, sizeof(data));
    
    return 0;
}

char _license[] SEC("license") = "GPL";
int _version SEC("version") = 99;

當我使用root@this:/home/ubuntu/Desktop/ebpf/Linux-exFilter-main/pkg/probe/bpf# clang -v trace_output_user.c -o trace -lbpf編譯和鏈接程序用戶空間時

我收到錯誤並警告

trace_output_user.c:101:7: warning: 'perf_buffer__new_deprecated' is deprecated: libbpf v0.7+: use new variant of perf_buffer__new() instead [-Wdeprecated-declarations]
        pb = perf_buffer__new_deprecated(map_fd, 8, &pb_opts);
             ^
/usr/include/bpf/libbpf.h:949:12: note: 'perf_buffer__new_deprecated' has been explicitly marked deprecated here
LIBBPF_API LIBBPF_DEPRECATED_SINCE(0, 7, "use new variant of perf_buffer__new() instead")
           ^
/usr/include/bpf/libbpf_common.h:24:4: note: expanded from macro 'LIBBPF_DEPRECATED_SINCE'
                (LIBBPF_DEPRECATED("libbpf v" # major "." # minor "+: " msg))
                 ^
/usr/include/bpf/libbpf_common.h:19:47: note: expanded from macro 'LIBBPF_DEPRECATED'
#define LIBBPF_DEPRECATED(msg) __attribute__((deprecated(msg)))
                                              ^
1 warning generated.
 "/usr/bin/ld" -z relro --hash-style=gnu --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o trace /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/10/crtbegin.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/10 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib64 -L/usr/lib/x86_64-linux-gnu/../../lib64 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../.. -L/usr/lib/llvm-12/bin/../lib -L/lib -L/usr/lib /tmp/trace_output_user-ec780e.o -lbpf -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/bin/../lib/gcc/x86_64-linux-gnu/10/crtend.o /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o
/usr/bin/ld: /tmp/trace_output_user-ec780e.o: in function `main':
trace_output_user.c:(.text+0x1e2): undefined reference to `perf_buffer__new_deprecated'

一些細節 perf_buffer__new_deprecated 和 perf_buffer__new 在 libbpf 的最新版本中被貶值 我的 kernel 版本是 5.14.1

1.您在代碼中明確使用perf_buffer__new_deprecated -不要這樣做:改用perf_buffer_new 您永遠不應調用名稱中已包含“已棄用”的 function。

2.查看header: libbpf/libbpf.h

perf_buffer_new定義如下:

#define perf_buffer__new(...) ___libbpf_overload(___perf_buffer_new, __VA_ARGS__)

#define ___perf_buffer_new6(map_fd, page_cnt, sample_cb, lost_cb, ctx, opts) \
    perf_buffer__new(map_fd, page_cnt, sample_cb, lost_cb, ctx, opts)

#define ___perf_buffer_new3(map_fd, page_cnt, opts) \
    perf_buffer__new_deprecated(map_fd, page_cnt, opts)

所以有2個功能:

  • 舊:pef_buffer_new 與 3 arguments
  • 新:perf_buffer_new 帶有 6 個 arguments。

使用宏, libbpf也可以編譯舊代碼,同時告訴您更改 function 調用。 您現在使用的是舊版本(帶有 3 個參數)。 使用 6 arguments 切換到新版本,因為 3-arguments-variant 將被刪除。

新的 function(參見libbpf/libbpf.h ):

/**
 * @brief **perf_buffer__new()** creates BPF perfbuf manager for a specified
 * BPF_PERF_EVENT_ARRAY map
 * @param map_fd FD of BPF_PERF_EVENT_ARRAY BPF map that will be used by BPF
 * code to send data over to user-space
 * @param page_cnt number of memory pages allocated for each per-CPU buffer
 * @param sample_cb function called on each received data record
 * @param lost_cb function called when record loss has occurred
 * @param ctx user-provided extra context passed into *sample_cb* and *lost_cb*
 * @return a new instance of struct perf_buffer on success, NULL on error with
 * *errno* containing an error code
 */
LIBBPF_API struct perf_buffer *
perf_buffer__new(int map_fd, size_t page_cnt,
         perf_buffer_sample_fn sample_cb, perf_buffer_lost_fn lost_cb, void *ctx,
         const struct perf_buffer_opts *opts);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM