Dev/InitrdVSInitramfs: Difference between revisions
No edit summary |
|||
Line 1: | Line 1: | ||
{{DISPLAYTITLE:Initrd VS Initramfs}} | |||
This may feel strange, but there is a persistant confusion around these two very different solutions. | This may feel strange, but there is a persistant confusion around these two very different solutions. | ||
Latest revision as of 19:29, 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
The Linux kernel includes support tools to build an initramfs cpio image.
You can either use this tool manually if you want to generate your own separate initramfs image, or simply set the "initramfs sources" configuration within the kernel configuration menu, and you'll get an embedded initramfs image.
If you want to use the manual solution :
Unlike the many other usefull tools which are under "tools/" and "scripts/", this one is under "usr/". You will first need to have "gen_init_cpio" compiled (for your host) though it should be made automatically if you activated initramfs supprt in your kernel configuration.
Then use "usr/gen_initramfs.sh" according to your needs.
For the "in kernel" solution, under "General setup" you have an "Initramfs source file(s)" entry which can contain a cpio archive name, directory names, or file names (, are all of these. The initramfs build script will use all of these sources to build the final initramfs image, so you can have a "base" cpio archive, and a file listing the modules you want to find in the initramfs.
For accurate, complete and up-to-date information, have a look at the help for this configuration entry, and the documentation within the kernel sources (Documentation/driver-api/early-userspace/early_userspace_support.rst).
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 !).