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  }