github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/examples/kprobe_percpu/main.go (about) 1 // This program demonstrates attaching an eBPF program to a kernel symbol and 2 // using percpu map to collect data. The eBPF program will be attached to the 3 // start of the sys_execve kernel function and prints out the number of called 4 // times on each cpu every second. 5 package main 6 7 import ( 8 "log" 9 "time" 10 11 "github.com/cilium/ebpf/link" 12 "github.com/cilium/ebpf/rlimit" 13 ) 14 15 //go:generate go run github.com/cilium/ebpf/cmd/bpf2go bpf kprobe_percpu.c -- -I../headers 16 17 const mapKey uint32 = 0 18 19 func main() { 20 21 // Name of the kernel function to trace. 22 fn := "sys_execve" 23 24 // Allow the current process to lock memory for eBPF resources. 25 if err := rlimit.RemoveMemlock(); err != nil { 26 log.Fatal(err) 27 } 28 29 // Load pre-compiled programs and maps into the kernel. 30 objs := bpfObjects{} 31 if err := loadBpfObjects(&objs, nil); err != nil { 32 log.Fatalf("loading objects: %v", err) 33 } 34 defer objs.Close() 35 36 // Open a Kprobe at the entry point of the kernel function and attach the 37 // pre-compiled program. Each time the kernel function enters, the program 38 // will increment the execution counter by 1. The read loop below polls this 39 // map value once per second. 40 kp, err := link.Kprobe(fn, objs.KprobeExecve, nil) 41 if err != nil { 42 log.Fatalf("opening kprobe: %s", err) 43 } 44 defer kp.Close() 45 46 // Read loop reporting the total amount of times the kernel 47 // function was entered, once per second. 48 ticker := time.NewTicker(1 * time.Second) 49 defer ticker.Stop() 50 51 log.Println("Waiting for events..") 52 53 for range ticker.C { 54 var all_cpu_value []uint64 55 if err := objs.KprobeMap.Lookup(mapKey, &all_cpu_value); err != nil { 56 log.Fatalf("reading map: %v", err) 57 } 58 for cpuid, cpuvalue := range all_cpu_value { 59 log.Printf("%s called %d times on CPU%v\n", fn, cpuvalue, cpuid) 60 } 61 log.Printf("\n") 62 } 63 }