The basic idea behind initramfs is that a (gzipped) cpio archive can be attached to the kernel image itself. At boot time, the kernel unpacks that archive into a RAM-based disk, which is then mounted and used at the initial root filesystem. Much of the kernel initialization and bootstrap code can then be moved into this disk and run in user mode. Tasks like finding the real root disk, boot-time networking setup, handling of initrd-style ramdisks, ACPI setup, etc. will be shifted out of the kernel in this way.
An obvious advantage of this scheme is that the size of the kernel code itself can shrink. That does not free memory for a running system, since the Linux kernel already dumps initialization code when it is no longer needed. But a smaller code base for the kernel itself makes the whole thing a little easier to maintain, and that is always a good thing. But the real advantages of initramfs are:
- Customizing the early boot process becomes much easier. Anybody who needs to change how the system boot can now do so with user-space code; patching the kernel itself will no longer be required.
- Moving the initialization code into user space makes it easier to write that code - it has a full C library, memory protection, etc.
- user-space code is required to deal with the kernel via system calls. This requirement will flush a lot of in-kernel "magic" currently used by the initialization code; the result will be cleaner, safer code.
It includes :
- A small C library ("klibc") will be merged to support initramfs applications.
- A small kinit application will be created with klibc. In the beginning, it will only do enough work to show that the mechanism is functioning properly.
- The Initrd (initial ramdisk) subsystem will be moved into kinit, and out of the kernel itself.
- The mounting of the root filesystem will be moved to user space. A lot of code for dealing with things like NFS-mounted root filesystems will go away.
The kernel has currently 3 ways to mount the root filesystem:
- all required device and filesystem drivers compiled into the kernel, no initrd. init/main.c:init() will call prepare_namespace() to mount the final root filesystem, based on the root= option and optional init= to run some other init binary than listed at the end of init/main.c:init().
some device and filesystem drivers built as modules and stored in an Initrd. The initrd must contain a binary '/linuxrc' which is supposed to load these driver modules. It is also possible to mount the final root filesystem via linuxrc and use the pivot_root syscall. The initrd is mounted and executed via prepare_namespace().
- using initramfs. The call to prepare_namespace() must be skipped. This means that a binary must do all the work. Said binary can be stored into initramfs either via modifying usr/gen_init_cpio.c or via the new initrd format, an cpio archive. It must be called "/init". This binary is responsible to do all the things prepare_namespace() would do.
To remain backwards compatibility, the /init binary will only run if it comes via an initramfs cpio archive. If this is not the case, init/main.c:init() will run prepare_namespace() to mount the final root and exec one of the predefined init binaries