Progress pill
Kernel level

System libraries

  • Static libraries
  • Dynamic libraries
  • ELF format
  • Glibc
  • C runtime

Static libraries

A library is just reusable code that many programs can use. Modern programming languages like Go or Rust are oriented towards producing static libraries.
With a static library, the code a program needs from that library is bundled into the final executable. The build toolchain takes your program’s compiled code and the compiled code from the libraries it uses, and produces a single self-contained executable.
If everything needed by the program is statically linked, at run time the kernel only has to load that one file, because all the needed code is already inside the executable image.

Dynamic libraries

Dynamic libraries work differently. The library code stays in separate files, and the executable only contains references to them. The executable says "when this runs, I expect the system to provide these libraries, with these interfaces". When the program starts, the OS uses a linker, which is a piece of software responsible for locating the right library files on the system, loading them into memory and connecting the program’s references to the code and data inside those libraries. If the expected libraries are missing or incompatible, the program cannot start correctly.
Dynamic linking was originally motivated by tight hardware constraints: early systems had very limited memory and storage, so sharing common code between many processes and many executables saved a lot of space. Instead of having a copy of the same library code inside every program, one copy could be stored on disk and mapped into multiple processes at run time. This is why dynamic linking is very common among Linux libraries and programs.

ELF format

On Linux, that standard format for programs and libraries is called ELF, which stands for Executable and Linkable Format.
An ELF file contains headers that describe its type and contents. These headers say whether the file is an executable or a library. They describe which parts of the file should be loaded into memory when the program starts, and where the entry point is. For dynamically linked executables, the ELF metadata also records which shared libraries are required, so that the linker can fetch them.

glibc

Almost all user-space programs on a Linux system depend on its standard C library, commonly referred to as glibc (GNU C library). Glibc provides basic building blocks such as input and output functions, memory allocation and string handling. It also provides the thin user-space wrappers around system calls (which are usually written in assembly), so that calling a kernel service from C code looks like a normal C function call.
Glibc itself is stored as an ELF shared library file. That means it is handled like any other shared library: the dynamic linker loads glibc into memory when the program starts. Because almost all programs rely on glibc, it is usually one of the first shared libraries that gets loaded.
(Glibc is an almost 40 years old piece of software and it has a lot of issues. The fact that the majority of the Linux ecosystem depends on it has been widely critized, and that has prompted the development of alternatives like the musl standard library, which is used in major Linux-derived projects like Android and Alpine Linux.)

C runtime

Within the C standard library there is a specific subset of code often referred to as the C runtime. The C runtime is the part that runs before and after the program’s main function. It sets up the initial process environment (arguments, environment variables and initial data areas), calls the main function of the program, and then handles the program’s termination and exit status.
The startup sequence of a program therefore involves several steps.
  1. The kernel loads the executable
  2. The kernel examines its ELF headers and starts the dynamic linker.
  3. The dynamic linker (usually) loads the C standard library and any other required shared libraries.
  4. Control is passed into the C runtime entry point supplied by the standard library.
  5. Only after the C runtime has finished its setup does it call the program’s main function.