linux-kernel-boot
Overview
why need intial ram disk
Many Linux distributions ship a single, generic Linux kernel image – one that the distribution’s developers create specifically to boot on a wide variety of hardware. The device drivers for this generic kernel image are included as loadable kernel modules because statically compiling many drivers into one kernel causes the kernel image to be much larger
, in some cases to cause boot-time crashes or other problems due to probing for inexistent or conflicting hardware. This static-compiled kernel approach also leaves modules in kernel memory which are no longer used or needed
, and raises the problem of detecting and loading the modules necessary to mount the root file system at boot time, or for that matter, deducing where or what the root file system is
.
To avoid having to hardcode handling for so many special cases into the kernel, an initial boot stage with a temporary root file-system(ram disk with temporary root fs) is used. This temporary root file-system can contain user-space helpers which do the hardware detection, module loading and device discovery necessary to get the real root file-system mounted
initial ramdisk is for loading a temporary root file system into memory
, to be used as part of the Linux startup process. initrd
and initramfs
refer to two different methods of achieving this
. Both are commonly used to make preparations before the real root file system can be mounted, if no real root file system is proivdes, the initial ramdisk is used for root file system which is in memory.
The bootloader will load the kernel and initial root file system image into memory and then start the kernel, passing in the memory address of the image. At the end of its boot sequence, the kernel tries to determine the format of the image from its first few blocks of data
, which can lead either to the initrd or initramfs scheme
.
initial root file system image format schema
initrd scheme
: the image may be a file system image (optionally compressed), which is made available in a special block device (/dev/ram) that is then mounted as the initial root file system during boots, The driver for that file system must be compiled statically into the kernel. Many distributions originally used compressed ext2 file system images. Once the initial root file system is up, thekernel executes /linuxrc as its first process
; when it exits, the kernel assumes that the real root file system has been mounted and executes /sbin/init to begin the normal user-space boot process.A ramdev block device is created
(default fixed size 16M). It is a ram-based block device, that is a simulated hard disk that uses memory instead of physical disks.- The
initrd file is read and unzipped into the device
, as if you did zcat initrd | dd of=/dev/ram0 or something similar. - The initrd contains an image of a filesystem, so now you can mount the filesystem as usual:
mount /dev/ram0 /root
. Naturally, filesystems need a driver, so if you use ext2, the ext2 driver has to be compiled in-kernel. exec /linuxrc
as first process which mount real root file system, then call /sbin/init to begin user-space boot process.
initramfs scheme
: (available since the Linux kernel 2.6.13), the image may be a cpio archive (optionally compressed). The archive is unpacked by the kernel into a special instance of a tmpfs that becomes the initial root file system. This scheme has the advantage of not requiring an intermediate file system or block drivers to be compiled into the kernel. In the initramfs scheme, thekernel executes /init as its first process
that is not expected to exit.- A tmpfs is mounted:
mount -t tmpfs nodev /root
. The tmpfs doesn’t need a driver, it is always on-kernel. No device needed, no additional drivers. - The
initramfs is uncompressed directly into this new filesystem
: zcat initramfs | cpio -i, or similar. exec /init
never exit
- A tmpfs is mounted:
initrd and initramfs
initrd schema
- initrd is for Linux kernels 2.4 and lower.
- Initrd requires at least one file system driver be compiled into the kernel
- A disk created by Initrd has got to have a fixed size
- All of the reads/writes on Initrd are buffered redundantly (unnecessarily) into main memory
So, initrd is deprecated and is replaced by initramfs.
1 | # inspect initrd image(it's disk) |
initramfs schema
- initramfs is a Linux 2.6 and above.
- This feature is made up from a cpio archive of files that enables an initial root filesystem and init program to reside in kernel memory cache, rather than on a ramdisk, as with initrd filesystems.
- with initramfs, you create an archive with the files which the kernel extracts to a tmpfs.
- intramfs can increase boot-time flexibility, memory efficiency, and simplicity
- dracut is the tool used to create the initramfs image.
- initramfs location of init : /init
1 | # inspect initramfs(it's just root file system) |
create initramfs
Actually, initramfs is created when you build kernel, you can also create initramfs with other tools without build your kernel.
When we first boot, we need at least some tools to start working. This includes the init process and some tools like ls, mount, mv, etc. To get those user space tools you can use BusyBox. BusyBox
has many useful commands available for just 1.1MB, it’s a binary that support many command
1 | # use busybox |
create_initramfs.sh
1 |
|
boot with disk/diskless
1 | # root filesystem is in an ext2 "hard disk" |
ramfs vs tmpfs
A ramdisk
is a volatile storage space defined in the RAM memory. all information stored in it will be lost if the device is umounted or system reboots.
In Linux, ramdisks can be created using the command mount and the filesystems tmpfs and ramfs
Tmpfs: Tmpfs is a temporary file system stored
in the RAM memory (and/or swap memory)
. By specifying this file system with the argument -t of the command mount, you can assignlimited memory resources to a temporary file system
.- stored in ram and swap memory
- ensure a limit
- adjusted on the fly via ‘mount -o remount …’
- Normal users can be allowed write access to tmpfs mounts!
Ramfs: Ramfs is similar to Tmpfs, it uses ram memory only and the user
can’t ensure a limit
, and the allocated resource grows dynamically. If the user doesn’t control the ramfs consumption, ramfs will keep using all the memory until hanging or crashing the system- stored in ram only
- can not ensure a limit, but traditonal ram disk (/dev/ramX) has fixed size, default is 16M
- cant adjust size on the fly for /dev/ramX, you need to reboot system or reload kernel module brd.
- only root use can access ramfs mounts!
ram disk(ramfs)
As mentioned above, they are two ways to create ram disk, one is using ramfs, the other is using tmpfs.
- enable traditional ram disk
old system ram disk is built into kernel with these kernel configs, that means after system boots, you will seee/dev/ram0, /dev/ram1, /dev/ramX
which has default fixed size configured during kernel compiling. even you have 16/dev/ramX
, the memory for each block device is not prealloated, memory allocation happens when make fs on that device.new system newer system by default compile it as kernel module1
2
3CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=16384brd
, you need to load this module when using/dev/ramX
1
2
3CONFIG_BLK_DEV_RAM=m
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=16384 - change traditonal ram disk size
old system ram disk is built into kernel, there is only one way to change ram disk ize, that’s by appending parmaters to kernel boot line like this.new system ram disk szie can be changed only when1
kernel /vmlinuz-2.6.32.24 ro root=LABEL=/ rhgb quiet ramdisk_size=10485760
brd
is loaded1
2# 1G, one ram disk /dev/ram0
$ modprobe brd rd_nr=1 rd_size=1048576 - use traditional ram disk
1
2
3
4
5
6
7
8$ mkfs /dev/ram0
$ mkdir /mnt/randisk
$ mount /dev/ram0 /mnt/ramdisk
$ df -h
df -h
Filesystem Size Used Avail Use% Mounted on
...
/dev/ram0 16M 140K 15M 1% /mnt/ramdisk - use ramfs not /dev/ramX(
brd
is not needed for this)1
$ mount -t ramfs ramfs /tmp/ramdisk
ram disk(tmpfs)
Use tmpfs to create ram disk is easy.1
2
3
4
5
6
7
8# memory is allocated only when it's used, it's not prereserved.
$ mount -t tmpfs -o size=10G none /tmp/ramdisk
(base) [root@dev github]# df -h
...
none 10G 0 10G 0% /tmp/ramdisk
(base) [root@dev github]# mount
none on /tmp/ramdisk type tmpfs (rw,relatime,seclabel,size=10485760k)
As when umount data on ram disk is gone, hence in order to save data in ram disk when reboot, we need a service that will copy data from ram disk to hard disk also copy it back to ram disk.
1 | $ vi /lib/systemd/system/ramdisk-sync.service |
Acutally, there are some ram disk(tmpfs) created by systemd if you check with df, it’s /run/
and /dev/shm
, sys/fs/cgroup
with default size(half of total physical memory)
1 | (base) [root@dev etc]# df |
resize /dev/shm
1 | Edit file /etc/fstab (with sudo if needed). |