Welcome to part 2 of Initramfs and Initrd series.
In Part 1 of this series we saw what is initramfs and how to compress and de-compress it. In this part we will see what is an initrd and some of the similarities between initramfs and initrd.
So as mentioned in first part, initramfs replaced the old initrd. So basically this means that there might be something lacking in initrd which made Linux kernel developers to come up with initramfs concept. As far as Debian is concerned, I think from 2.6.15 kernel Debian started shipping initramfs instead of initrd. I am not 100% sure but you can refer to this page for more details on the transition from initrd to initramfs in Debian.
Before we begin, I would like to mention once more that the discussion in this post regarding initrd is just for historical purpose. Initrd has now been replaced by initramfs. So most of the things that we are discussing with regards to initrd as now obsolete.
What is initrd?
So initrd stands for initial ram disk. It is a (generally gzipped compressed) ext2 filesystem (just like your hard drive file system) but it resides in RAM (/dev/ram0). Because of this, initrd has a fixed size and it cannot be dynamically shrink or grow as required. This leads to a lot of memory wastage due to cache related issues. We won’t go into those details here but you can refer to this article if you are further interested. From the kernel docs:
initrd provides the capability to load a RAM disk by the boot loader. This RAM disk can then be mounted as the root file system and programs can be run from it. Afterwards, a new root file system can be mounted from a different device. The previous root (from initrd) is then moved to a directory and can be subsequently unmounted.
initrd is mainly designed to allow system startup to occur in two phases, where the kernel comes up with a minimum set of compiled-in drivers, and where additional modules are loaded from initrd.
Basically your bootloader (GRUB or LILO) loads the initrd along with the corresponding kernel (just like we initramfs) into the RAM and the kernel mounts the initrd as a temporary root filesystem (early user space) as a “normal” RAM disk and then executes the “linuxrc” and/or “init” file from it. The “linuxrc” or “init” file is now responsible for loading the “real” root filesystem, typically from hard drive. In case of initrd, pivot_root call is used to mount the real root filesytem. Also there is still some confusion within myself regarding the use of “linuxrc” file. Some versions of initrd used the linuxrc file and some didn’t. Instead they used the “init” method just like initramfs. There is a lot of overlap and confusion with regards to this. However, I still think that “linuxrc” method is obsolete in initrd also now. And initrd in turn is now obsolete.
What’s up with this “init” executable file?
Once the kernel is loaded into the RAM, it runs it’s initialization/boot code. You can see the Linux kernel’s init code from the following source directory:
# ls /usr/src/linux-source-2.6.30/init/
calibrate.c do_mounts_initrd.c initramfs.c Makefile
do_mounts.c do_mounts_md.c Kconfig noinitramfs.c
do_mounts.h do_mounts_rd.c main.c version.c
Now from the file main.c from the above directory we see that in the function init_post:
So basically once the kernel initializes the CPU subsystem, memory, etc. it tries to find a executable file called “init” in the above 3 locations and usually this “init” file should be present on your root filesystem. Note that the “init” is the first user space program that is run by the kernel with process ID 1. It is the mother of all other process.
Note: Please note that the above whole process of finding init is true for initramfs also. If you de-compress your initramfs you will find that executable init in the “/” which is symlinked to /sbin/init.
Who creates initrd and initramfs?
Generally when you build a Linux kernel, the compilation process generates a matching/corresponding initrd file which has all the necessary modules/drivers to load the real root filesystem. Optionally, once can also manually create an initrd file by using the mkinitrd command and use that instead of the one generated by default during the compilation process. Similarly initramfs is created by the command update-initramfs or mkinitramfs.
Do I always need initrd and initramfs?
No. If your kernel is compiled (=y) with everything that it requires to mount your root filesystem then it does not need to use an initrd/initramfs file. I prefer building my kernel in this way i.e. which does not involve using initramfs image and all that. Basically to get rid of initrd/initramfs, you need to make sure that the kernel has drivers for your root filesystem (ext3/ext2,etc.) and for your IDE/SATA controller built into the kernel. Someday I plan to write a detailed post on this.