golang、ebpf 和函数持续时间

我正在玩 gobpf 并且在计算跟踪用户空间函数的持续时间时遇到了问题。我使用 bpf_ktime_get_ns() 读取时间,然后尝试计算增量,但得到了巨大的数字,尽管跟踪函数仅休眠 1 秒。


这是经过测试的 C 程序,它有一个名为“ameba”的函数。


#include <stdio.h>

#include <strings.h>

#include <stdlib.h>

#include <time.h>

#include <unistd.h>


char * ameba(char * s1, char * s2);


int main(void) {

    time_t rawtime;

    struct tm * timeinfo;


    time(&rawtime);

    timeinfo = localtime(&rawtime);

    printf("enter: %s", asctime (timeinfo));

    printf("%s\n", ameba("lessqqmorepewpew", "good luck, have fun"));


    time(&rawtime);

    timeinfo = localtime(&rawtime);

    printf("return: %s", asctime(timeinfo));

}


char * ameba(char * s1, char * s2) {

    char *s;

    s = (char *) malloc(128);

    sleep(1);

    snprintf(s, 128, "phrase1: %s, phrase2: %s", s1, s2);

    return s;

}

去代码


package main


import (

    "bytes"

    "encoding/binary"

    "fmt"

    "os"

    "os/signal"

    "time"


    bpf "github.com/iovisor/gobpf/bcc"

)


const source string = `

#include <uapi/linux/ptrace.h>

#include <linux/sched.h>

struct val_t {

    u32 pid;

    char comm[TASK_COMM_LEN];

    u64 ts;

};

struct data_t {

    u32 pid;

    char comm[TASK_COMM_LEN];

    u64 delta;    

};

BPF_HASH(start, u32, struct val_t);

BPF_PERF_OUTPUT(ameba_events);

int do_entry(struct pt_regs *ctx) {

    if (!PT_REGS_PARM1(ctx))

        return 0;

    struct val_t val = {};

    u32 pid = bpf_get_current_pid_tgid();

    if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) {

        val.pid = bpf_get_current_pid_tgid();

        val.ts = bpf_ktime_get_ns();

        start.update(&pid, &val);

    }

    return 0;

}

int do_return(struct pt_regs *ctx) {

    struct val_t *valp;

    struct data_t data = {};

    u64 delta;

    u32 pid = bpf_get_current_pid_tgid();

    u64 tsp = bpf_ktime_get_ns();

    valp = start.lookup(&pid);


    if (valp == 0)

        return 0;       // missed start


    bpf_probe_read(&data.comm, sizeof(data.comm), valp->comm);

    data.pid = valp->pid;

    data.delta = tsp - valp->ts;

    ameba_events.perf_submit(ctx, &data, sizeof(data));

    start.delete(&pid);


    return 0;

}


错在哪里??


子衿沉夜
浏览 115回答 1
1回答

噜噜哒

这看起来是由内核和用户端之间的填充不匹配引起的。该data_t结构实际上在编译时被填充为等同于以下内容:struct data_t {   u32 pid;   char padding[4];   char comm[TASK_COMM_LEN];   u64 delta;    };如果你明确地在 Go 端添加相同的填充,你的问题就会消失:type amebaEvent struct {    Pid uint32    Pad [4]byte    Comm [16]byte    Delta uint64}生产:PID COMMAND DURATION    RAW8258    a   1.000179625s    10001796258260    a   1.000158337s    1000158337
打开App,查看更多内容
随时随地看视频慕课网APP