// link to the tracepoint program that we loaded into the kernel tp, err := link.Tracepoint("sched", "sched_switch", objs.CpuProcessingTime, nil) if err != nil { log.Fatalf("opening kprobe: %s", err) } defer tp.Close()
// used as HashMap Key type processtimeKeyT struct{ Pid uint32 } // used as HashMap Value type processtimeValT struct { StartTime uint64 ElapsedTime uint64 }
这与我们在 C 程序中使用的两种类型相关:
1 2 3 4 5 6 7 8 9
// used as Hashmap Key struct key_t { __u32 pid; }; // used as Hashmap Value struct val_t { __u64 start_time; __u64 elapsed_time; };
var key processtimeKeyT // Iterate over all PIDs between 1 and 32767 (maximum PID on linux) // found in /proc/sys/kernel/pid_max for i := 1; i <= 32767; i++ { key.Pid = uint32(i) // Query the BPF map var mapValue processtimeValT if err := objs.ProcessTimeMap.Lookup(key, &mapValue); err == nil { log.Printf("CPU time for PID=%d: %dns\n", key.Pid, mapValue.ElapsedTime) } }
// Load the compiled eBPF ELF and load it into the kernel. var objs processtimeObjects if err := loadProcesstimeObjects(&objs, nil); err != nil { log.Fatal("Loading eBPF objects:", err) } defer objs.Close()
// link to the tracepoint program that we loaded into the kernel tp, err := link.Tracepoint("sched", "sched_switch", objs.CpuProcessingTime, nil) if err != nil { log.Fatalf("opening kprobe: %s", err) } defer tp.Close()
// Read loop reporting the total amount of times the kernel // function was entered, once per second. ticker := time.NewTicker(1 * time.Second) defer ticker.Stop()
log.Println("Waiting for events..") for range ticker.C { var key processtimeKeyT
// Iterate over all PIDs between 1 and 32767 (maximum PID on linux) // found in /proc/sys/kernel/pid_max for i := 1; i <= 32767; i++ { key.Pid = uint32(i) // Query the BPF map var mapValue processtimeValT if err := objs.ProcessTimeMap.Lookup(key, &mapValue); err == nil { log.Printf("CPU time for PID=%d: %dns\n", key.Pid, mapValue.ElapsedTime) } } } }