为了账号安全,请及时绑定邮箱和手机立即绑定

golang、ebpf 和函数持续时间

golang、ebpf 和函数持续时间

Go
子衿沉夜 2023-05-08 16:26:36
我正在玩 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 mainimport (    "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;}错在哪里??
查看完整描述

1 回答

?
噜噜哒

TA贡献1784条经验 获得超7个赞

这看起来是由内核和用户端之间的填充不匹配引起的。该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    RAW

8258    a   1.000179625s    1000179625

8260    a   1.000158337s    1000158337


查看完整回答
反对 回复 2023-05-08
  • 1 回答
  • 0 关注
  • 111 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信