8.6 Disk Filesystem over RAM Disk

RAM disks, as their name indicates, live in RAM and act like block devices. The kernel supports having many RAM disks active in the same time. Because they act like block devices, any disk filesystem can be used with them. Since their content lasts only as long as the system isn't rebooted, RAM disks are usually populated using compressed images of disk filesystems, such as ext2, known as compressed RAM disk images. One instance where the use of such compressed RAM disk images is particularly attractive for embedded Linux systems is during system initialization. Mainly, the kernel is capable of extracting an initial RAM disk (initrd) image from a storage device for use as its root filesystem. At startup, the kernel verifies whether its boot options indicate the presence of an initird. If so, it extracts the filesystem image, whether it be compressed or not, from the designated storage media into a RAM disk, and mounts it as its root filesystem. The initrd mechanism is, in fact, the simplest method to provide a kernel with its root filesystem. In this section, we will discuss the creation of a compressed RAM disk image for use as an initrd. I will explain how this image can actually be used as an initrd in Chapter 9.

For our purposes, we will create an ext2-based RAM disk image for use in our target. Although ext2 is the filesystem most commonly used with RAM disks, other disk filesystems can also be used, as I hinted to above. Some developers, for instance, report using CRAMFS instead.

Note that although we are creating a filesystem image for use on a RAM disk in the following procedures, all the operations are carried out on your host's disk. Hence, none of the following steps involve using an actual RAM disk on the host.

First, create a blank filesystem image for the root filesystem:

$ cd ${PRJROOT}
$ mkdir tmp/initrd
$ dd if=/dev/zero of=images/initrd.img bs=1k count=8192
8192+0 records in
8192+0 records out

The dd command creates a 8192 KB filesystem image and initializes it using /dev/zero. By initializing the filesystem in this way, we will achieve a maximum compression ratio for the unused portions of the filesystem later when we use gzip to compress the entire image. In comparison, if we were to reuse an existing image of the same size as the one we need, such as an image created previously following this section's instructions, instead of using the dd command as shown above, the image's compression would yield a lower compression ratio given that it already contains non-uniform data. Practically, this means that you should never try updating an existing filesystem image. Instead, always create a fresh filesystem image using your target's updated root filesystem directory, ${PRJROOT}/rootfs.

With the filesystem image initialized, create a filesystem on it and mount it:

$ su -m
# /sbin/mke2fs -F -v -m0 images/initrd.img
mke2fs 1.18, 11-Nov-1999 for EXT2 FS 0.5b, 95/08/09
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
2048 inodes, 8192 blocks
0 blocks (0.00%) reserved for the super user
First data block=1
1 block group
8192 blocks per group, 8192 fragments per group
2048 inodes per group
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
# mount -o loop images/initrd.img tmp/initrd

We use the -F option with mke2fs to force it to run on a file. Otherwise, mke2fs complains that images/initrd.img is not a block device. The -v option specifies that the command should be verbose, and the -m0 option specifies that no blocks should be reserved for the super user on the filesystem. Whereas reserving blocks for the super user makes sense for a filesystem created for use in a workstation or server, it isn't very useful in embedded systems, since they are usually built as single-user systems.

Now, copy the root filesystem to the RAM disk and unmount it:

# cp -av rootfs/* tmp/initrd
rootfs/bin -> tmp/initrd/bin
rootfs/bin/busybox -> tmp/initrd/bin/busybox
rootfs/bin/ash -> tmp/initrd/bin/ash
rootfs/bin/cat -> tmp/initrd/bin/cat
rootfs/bin/chgrp -> tmp/initrd/bin/chgrp
rootfs/bin/chmod -> tmp/initrd/bin/chmod
# umount tmp/initrd
# exit

After issuing the first command, you will see the complete list of all the files in your root filesystem with their complete path as shown in the example. The images/initrd.img file now contains the complete root filesystem for your target. The final step is to compress this filesystem to obtain a compressed RAM disk:

$ gzip -9 < images/initrd.img > images/initrd.bin
$ ls -al images/initrd*
-rw-rw-r--   1 karim   karim    3101646 Aug 16 14:47 images/initrd.bin
-rw-rw-r--   1 karim   karim    8388608 Aug 16 14:46 images/initrd.img

The filesystem is compressed using the gzip command. The -9 option tells the command to use the highest compression algorithm available. In this case, the compression ratio is above 60%, which is superior to both CRAMFS and JFFS2. This gain is, however, subject to the caveat I mentioned earlier in Section 8.1 regarding the fact that RAM disks live in RAM.

You can place the RAM disk image created here, images/initrd.bin, on the appropriate device on your target and configure your bootloader accordingly. As I said earlier, we will discuss the use of RAM disks as initrds in Chapter 9.


At the time of this writing, though initrds are still commonly used, the initrd mechanism is increasingly showing its age, and kernel developers intend to replace it in the 2.5 series with init RAMFS (initramfs). In the future, each kernel is likely to have an initramfs image that would contain much of the initialization code currently hardcoded in the kernel. In that case, the definitive root filesystem would be mounted by the last procedure running on the initramfs using the pivot_root( ) system call once initialization is complete. Until initramfs becomes ready for mainstream use, initrds remain the standard way for providing a kernel with a root filesystem at boot time.