github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/docs/ebpf/concepts/object-lifecycle.md (about)

     1  !!! info ""
     2      This is an advanced topic and does not need to be fully understood in order
     3      to get started writing useful tools.
     4  
     5      If you find yourself debugging unexpectedly-detached programs, resource
     6      leaks, or you want to gain a deeper understanding of how eBPF objects are
     7      managed by {{ proj }}, this page should prove helpful.
     8  
     9  ## File Descriptors and Go
    10  
    11  Interacting with eBPF objects from user space is done using file descriptors.
    12  Counter-intuitively, 'file' descriptors are used as references to many types of
    13  kernel resources in modern Linux, not just files. In {{ proj }}, {{ godoc('Map')
    14  }}, {{ godoc('Program') }} and {{ godoc('link/Link') }} are all modeled around
    15  these underlying file descriptors.
    16  
    17  Go, being a garbage-collected language, automatically manages the lifecycle of
    18  Go objects. Keeping in line with the standard library's `os.File` and friends,
    19  eBPF resources in {{ proj }} were designed in a way so their underlying file
    20  descriptors are closed when their Go objects are garbage collected. This
    21  generally prevents runaway resource leaks, but is not without its drawbacks.
    22  
    23  This has subtle but important repercussions for BPF, since this means the Go
    24  runtime will call `Close()` on an object's underlying file descriptor if the
    25  object is no longer reachable by the garbage collector. For example, this can
    26  happen if an object is created in a function, but is not returned to the caller.
    27  One type of map, {{ godoc('ProgramArray') }}, is particularly sensitive to this.
    28  More about that in [Program Arrays](#program-arrays).
    29  
    30  ## Extending Object Lifetime
    31  
    32  ### Pinning
    33  
    34  Aside from file descriptors, BPF provides another method of creating references
    35  to eBPF objects: pinning. This is the concept of associating a file on a virtual
    36  file system (the BPF File System, bpffs for short) with a BPF resource like a
    37  Map, Program or Link. Pins can be organized into arbitrary directory structures,
    38  just like on any other file system.
    39  
    40  When the Go process exits, the pin will maintain a reference to the object,
    41  preventing it from being automatically destroyed. In this scenario, removing the
    42  pin using plain `rm` will remove the last reference, causing the kernel to
    43  destroy the object. If you're holding an active object in Go, you can also call
    44  {{ godoc('Map.Unpin') }}, {{ godoc('Program.Unpin') }} or {{
    45  godoc('link/Link.Unpin') }} if the object was previously pinned.
    46  
    47  !!! warning
    48      Pins do **not** persist through a reboot!
    49  
    50  A common use case for pinning is sharing eBPF objects between processes. For
    51  example, one could create a Map from Go, pin it, and inspect it using `bpftool
    52  map dump pinned /sys/fs/bpf/my_map`.
    53  
    54  ### Attaching
    55  
    56  Attaching a Program to a hook acts as a reference to a Program, since the kernel
    57  needs to be able to execute the program's instructions at any point.
    58  
    59  For legacy reasons, some {{ godoc('link/Link') }} types don't support pinning.
    60  It is generally safe to assume these links will persist beyond the lifetime of
    61  the Go application.
    62  
    63  ## :warning: Program Arrays
    64  
    65  A {{ godoc('ProgramArray') }} is a Map type that holds references to other
    66  Programs. This allows programs to 'tail call' into other programs, useful for
    67  splitting up long and complex programs.
    68  
    69  Program Arrays have a unique property: they allow cyclic dependencies to be
    70  created between the Program Array and a Program (e.g. allowing programs to call
    71  into themselves).To avoid ending up with a set of programs loaded into the
    72  kernel that cannot be freed, the kernel maintains a hard rule: **Program Arrays
    73  require at least one open file descriptor or bpffs pin**.
    74  
    75  !!! warning
    76      If all user space/bpffs references are gone, **any tail calls into the array
    77      will fail**, but the Map itself will remain loaded as long as there are
    78      programs that use it. This property, combined with interactions with Go's
    79      garbage collector previously described in [File Descriptors and
    80      Go](#file-descriptors-and-go), is a great source of bugs.
    81  
    82  A few tips to handle this problem correctly:
    83  
    84  - Use {{ godoc('CollectionSpec.LoadAndAssign') }}. It will refuse to load the
    85    CollectionSpec if doing so would result in a Program Array without a userspace
    86    reference.
    87  - Pin Program Arrays if execution of your eBPF code needs to continue past the
    88    lifetime of your Go application, e.g. for upgrades or short-lived CLI tools.
    89  - Retain references to the Map at all times in long-running applications. Note
    90    that `#!go defer m.Close()` makes Go retain a reference until the end of the
    91    current scope.