I found a wonderful explanation here. However, let me try to put in a shorter format of what I understood in the answer.
Shorter Version
- While the system boots, it needs an early userspace. It can be
achieved using either initramfs or initrd.
- initrd is loaded into ramdisk which is an actual FILE SYSTEM.
- initramfs is not a file system.
- For initrd
pivot_root
is used and for initramfs switch_root
is used.
Longer Version
Now, to the detailed explanation of what I had put above.
While both an initramfs and an initrd serve the same purpose, there
are 2 differences. The most obvious difference is that an initrd is
loaded into a ramdisk. It consists of an actual filesystem (typically
ext2) which is mounted in a ramdisk. An initramfs, on the other hand,
is not a filesystem. It is simply a (compressed) cpio archive (of type
newc) which is unpacked into a tmpfs. This has a side-effect of making
the initramfs a bit more optimized and capable of loading a little
earlier in the kernel boot process than an initrd. Also, the size of
the initramfs in memory is smaller, since the kernel can adapt the
size of the tmpfs to what is actually loaded, rather than relying on
predefined ramdisk sizes, and it can also clean up the ram that was
used whereas ramdisks tend to remain in use (due to details of the
pivot_root implementation).
There is also another side-effect difference: how the root device (and
switching to it) is handled. Since an initrd is an actual filesystem
unpacked into ram, the root device must actually be the ramdisk. For
an initramfs, there is a kernel "rootfs" which becomes the tmpfs that
the initramfs is unpacked into (if the kernel loads an initramfs; if
not, then the rootfs is simply the filesystem specified via the root=
kernel boot parameter), but this interim rootfs should not be
specified as the root= boot parameter (and there wouldn't be a way to
do so, since there's no device attached to it). This means that you
can still pass your real root device to the kernel when using an
initramfs. With an initrd, you have to process what the real root
device is yourself. Also, since the "real" root device with an initrd
is the ramdisk, the kernel has to really swith root devices from one
real device (the ramdisk) to the other (your real root). In the case
of an initramfs, the initramfs space (the tmpfs) is not a real device,
so the kernel doesn't switch real devices. Thus, while the command
pivot_root is used with an initrd, a different command has to be used
for an initramfs. Busybox provides switch_root to accomplish this,
while klibc offers new_root.