Dev/InitrdVSInitramfs: Difference between revisions

From Embeded Linux (and more) Wiki by Nathael
< Dev
Jump to navigation Jump to search
Line 61: Line 61:
== How to build them ==
== How to build them ==
=== initrd ===
=== initrd ===
An initrd is a "Disk image" wich will reside in RAM. As such you need to create a file the size of your "virtual" disk, and create a filesystem on it :
  dd if=/dev/zero of=disk.img bs=1M count=16
  dd if=/dev/zero of=disk.img bs=1M count=16
  mkfs.ext2 disk.img -L initrd
  mkfs.ext2 disk.img -L initrd
Then you can simply mount this virtual disk using the "loop" option to "mount" :
  mount -o loop disk.img /mnt/tmp/
  mount -o loop disk.img /mnt/tmp/
# Put your file in the initrd by copying them to the mountpoint
And put your files in the initrd by copying them to the mountpoint you chose.
 
Then you can unmount, and compress the result to get your initrd image :
  umount /mnt/tmp
  umount /mnt/tmp
  gzip -9 disk.img
  gzip -9 disk.img


=== initramfs ===
=== initramfs ===
The initramfs version is a cpio archive of your "future" rootfs.<br />
You have a few options to create your initramfs image.
==== simple, cmdline solution ====
Let's say that you put everything you wanted in your initramfs in the "test" directory, then :
  cd test && find . > ../liste_cpio
  cd test && find . > ../liste_cpio
  cat ../liste_cpio | cpio -H newc -o > ../initramfs.cpio
  cat ../liste_cpio | cpio -H newc -o > ../initramfs.cpio
  gzip -9 initramfs.cpio
  gzip -9 initramfs.cpio
  mv initramfs.cpio.gz initramfs.img.gz
  mv initramfs.cpio.gz initramfs.img.gz
And you're done.
==== using the kernel embedded scripts ====
==== using mkinitramfs ====
If you have "initramfs-tools" installed (Debian package), then you can try to configure and use "mkinitramfs".<br />
Aside from the fact that the configuration lies under "/etc/initramfs-tools/initramfs.conf" and "/etc/initramfs-tools/conf.d/*" I know very little of this solution, which is mainly intended for the creation of the initramfs for your host by your host.<br />
I never tried this for an embedded target.<br />
To be honest, I installed this solution to give it a try while writting these lines, but did not went very far (only ran "/sbin/mkinitramfs -o test" and "/sbin/mkinitramfs -h") and removed it already. I built the initramfs for my host myself, it's really pretty simple, and once you have it running no update/upgrade will try to change your stuff and render your system unusable (and most of the time you don't even need one !).

Revision as of 18:52, 15 January 2025

This may feel strange, but there is a persistant confusion around these two very different solutions.

Both of them (initrd and initramfs) have the same goal : provide an initial root files-system for the Linux kernel to mount on "/" at the end of the boot process.
Both of them are presented to the Linux kernel as a single file, possibly compressed.
And both of them can have exactly the same content.

But the similarities end here.

Some historical background

Before version 2.6 of the Linux kernel there was only one option : initrd. But starting with the release of linux-2.6 (December 2003) a new mechanism is available : initramfs.

The initramfs is not a replacement of initrd, just another solution, though both are supported using a single configuration entry within the Linux kernel :

Symbol: BLK_DEV_INITRD [=n]
Prompt: Initial RAM filesystem and RAM disk (initramfs/initrd) support

This does not help understanding the differences between these solutions.

To add to the confusion, the command to pass one of these (initrd or initramfs) to the Linux kernel under grub is still called "initrd" (while grub really does not care about the file content).

But much worse : many distributions keep naming the files "initrd". It is the name set by initramfs-tools : "initrd.img-${version}" (at least for Debian based GNU/Linux distributions).
As of January 2025, I found that gentoo now uses initramfs name, as well as Red Hat.

Technical differences

Despite the fact that both solutions can be used with recent Linux kernels (>= 2.6) to provide an initial root files-system, the solutions share very little.

Here are the common parts :

  • "Image" for the Linux kernel to mount on "/" at the end of the boot process.
  • Presented to the Linux kernel as a single file, possibly compressed.
  • Can have exactly the same content.

But these solutions are technically very different :

Initial RAM Disk image

An initial RAM Disk image, or "initrd", is an emulation of a disk drive (or partition to be exact : it does not allow further partitionning) in a file.

This means that it will be handled by the Linux kernel as though it was a real partition : with a fixed size, and with a real file-system on it. And as such, any access to a file will go through all the usual kernel mechanisms : internal cache copy, flushing, and so on.

It will also mean that modifications made on the decompressed version of the initrd file (when it is not in RAM) are persistent, which allows creation and modifications with the file decompressed on another filesystem and mounted as any common partition (using -o loop mount option).

You will need to choose a filesystem to format the file. It could be anything : vfat, ext*, zfs, btrfs, .... so long as you have the tools to create it and your kernel has this filesystem support built-in (not as a module).
Once you've chosen one, you cannot change. If you want another filesystem you'll need to create a new initrd, or re-format your file (and loose anything you had on it).
And of course, the filesystem related data structures will consume some place in your initrd file, which will not be available for the "useful" files.

The size if fixed to the size of the file holding the image. You will choose the file size when you create the initrd image, and changing the file size will not be enough to change the available size for the filesystem, exactly as if you changed the partition size in the partition table on a real hard drive. If you reduce the size before resizing the file-system you may loose some of the files contained within the image, and if you increase the file size, you will then need to increase the internal filesystem size, if the filesystem you use can support the operation.

Access to any file will imply copying the file to the kernel cache. This means that the file (or at least parts of the file) will be present twice in RAM.

Initial RAM filesystem image

An initial RAM Filesystem image, or "initramfs" is a "simple" cpio archive read "Why cpio rather than tar?" section in kernel initramfs documentation for an explanation of the choice).

When the kernel boots with initramfs support it will create a special instance of "ramfs" (or "tmpfs" when available) with the name "rootfs" in the RAM and extract the content of the cpio archive (built-in or external one) to this "rootfs".

"ramfs" and "tmpfs" work in almost the same way : they reside within the Kernel cache, directly in RAM, so there's no need for additional code to access the files and no need to synchronize with another copy of the file in RAM as he data will not be duplicated.
The advantage of "tmpfs" over "ramfs" is that it's size can be limited so it cannot end up consumming all available RAM space.
Note that "ramfs" is always supported, it cannot be excluded from the kernel.

Also, when a file is suppressed from the in-memory version of the initramfs (the "rootfs") it frees as much memory.

You can get some more information from the initramfs documentation in the Linux kernel sources. Note that some parts of this file seems to be obsolete (as well as some of the links).

How to build them

initrd

An initrd is a "Disk image" wich will reside in RAM. As such you need to create a file the size of your "virtual" disk, and create a filesystem on it :

dd if=/dev/zero of=disk.img bs=1M count=16
mkfs.ext2 disk.img -L initrd

Then you can simply mount this virtual disk using the "loop" option to "mount" :

mount -o loop disk.img /mnt/tmp/

And put your files in the initrd by copying them to the mountpoint you chose.

Then you can unmount, and compress the result to get your initrd image :

umount /mnt/tmp
gzip -9 disk.img

initramfs

The initramfs version is a cpio archive of your "future" rootfs.
You have a few options to create your initramfs image.

simple, cmdline solution

Let's say that you put everything you wanted in your initramfs in the "test" directory, then :

cd test && find . > ../liste_cpio
cat ../liste_cpio | cpio -H newc -o > ../initramfs.cpio
gzip -9 initramfs.cpio
mv initramfs.cpio.gz initramfs.img.gz

And you're done.

using the kernel embedded scripts

using mkinitramfs

If you have "initramfs-tools" installed (Debian package), then you can try to configure and use "mkinitramfs".
Aside from the fact that the configuration lies under "/etc/initramfs-tools/initramfs.conf" and "/etc/initramfs-tools/conf.d/*" I know very little of this solution, which is mainly intended for the creation of the initramfs for your host by your host.
I never tried this for an embedded target.
To be honest, I installed this solution to give it a try while writting these lines, but did not went very far (only ran "/sbin/mkinitramfs -o test" and "/sbin/mkinitramfs -h") and removed it already. I built the initramfs for my host myself, it's really pretty simple, and once you have it running no update/upgrade will try to change your stuff and render your system unusable (and most of the time you don't even need one !).