linux initrd 制作及使用

使用Ramdisk作为根文件系统,也就是INITRD

一, Ramdisk

Ram Disk 就是将内存中的一块区域作为物理磁盘来使用的一种技术。

使用时内核配置:两个选项:第一个设定Ramdisk个数,默认16个;第二个是设定Ramdisk的大小,设定16M

Device Drivers --->

[*] Block devices --->

<*> RAM block device support

(16) Default number of RAM disks

(16384) Default RAM disk size (kbytes)

另外:设置RAM disk 支持

General setup --->

[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support


二, initrd

initrd全称是 initial RAM disk ,它提供一种让核心可以简单使用Ramdisk的能力,简单的说,这些能力包括:

格式化一个 Ramdisk;

加载文件系统内容到Ramdisk;

将Ramdisk作为根文件系统;


而Linux启动阶段的Ramdisk相当于一个未格式化的硬盘分区,核心可以直接将initrd的内容释放到一个未初始化的Ramdisk里,这个过程与Ghost恢复一个分区的过程十分相似。于是,相应的内容被加载到相应的Ramdisk中,同时,这个Ramdisk也被格式化成某种由initrd格式所表达的分区格式。


initrd支持的格式

· Romfs文件系统;

· Ext2文件系统;

· cramfs文件系统;

· minix文件系统;


三, Gzip支持

如果核心选择了Gzip支持(通常这是默认的,在init/do_mounts_rd.c中定义的BUILD_CRAMDISK宏)还可以使用Gzip压缩的initrd。相关的代码可以在核心源码 drivers/block/rd.c:identify_ramdisk_p_w_picpath 中找到。


四, 制作initrd

initrd有两种格式,initrd-p_w_picpath和initrd-cpio。

办法一

通过ramdisk来制作的方法比较简单(以ext2文件系统为例):
redice # mkfs.ext2 /dev/ram0
redice # mount /dev/ram0 /mnt/rd
redice # cp _what_you_like_ /mnt/rd # 把需要的文件复制过去
redice # dd if=/dev/ram0 of=/tmp/initrd
redice # gzip -9 /tmp/initrd
这个过程也最能够解释initrd的本质,对于Linux来说,Ramdisk的一个块设备,而initrd是这个块设备上所有内容的“克隆”(由
命令dd来完成)而生成的文件。核心中加载initrd相关的代码则用于完成将相反的过程,即将这一个文件恢复到Ramdisk中去。

办法二

通过loop设备来制作initrd的过程:
redice # dd if=/dev/zero of=/tmp/initrd bs=1024 count=4096 # 制作一个4M的空白文件
redice # losetup /dev/loop0 /tmp/initrd # 映射到loop设备上;
redice # mkfs.ext2 /dev/loop0 # 创建文件系统;
redice # mount /dev/loop0 /mnt/rd
redice # cp _what_you_like_ /mnt/rd # 复制需要的文件;
redice # umount /mnt/rd
redice # losetup -d /dev/loop0
redice # gzip -9 /tmp/initrd

办法三

bash# dd if=/dev/zero of=../initrd.img bs=512k count=5
bash# mkfs.ext2 -F -m0 ../initrd.img
bash# mount -t ext2 -o loop ../initrd.img /mnt
bash# cp -r * /mnt
bash# umount /mnt
bash# gzip -9 ../initrd.img


办法四(新式INITRD:cpio-initrd的制作)

# find . | cpio -c -o > ../initrd.img
# gzip ../initrd.img解压initrd
gunzip initrd.img.gz
即使您的 initrd 映像文件不是以 .gz 结尾,它也可能是一个压缩文件,
可以给这个文件添加上 .gz后缀,然后再使用 gunzip 对其进行解压。

cpio 归档文件
# mkdir temp ; cd temp
# cp /boot/initrd-2.6.14.2.img initrd-2.6.14.2.img.gz   
# gunzip initrd-2.6.14.2.img.gz   
#cpio -ivmd < initrd-2.6.14.2.img

五, 启动:

Redboot启动。

下载initrd

0x01000000-0x01258831

下载zImage

0x00100000-0x002f82f7

启动命令

exec -r 0x1000000 -s 0x258831 -c "root=/dev/ram rw console=ttymxc0,115200"

六, 结果:

办法三制作,也就是initrd-p_w_picpath可以成功启动:

Kernel command line: root=/dev/ram rw console=ttymxc0,115200

checking if p_w_picpath is initramfs...it isn't (no cpio magic); looks like an initrd

Freeing initrd memory: 2402K

RAMDISK: Compressed p_w_picpath found at block 0

RAMDISK: ran out of compressed data

out of input data

VFS: Mounted root (ext2 filesystem).

Freeing init memory: 140K

Mounting /proc and /sys

Starting the hotplug events dispatcher udevd

Synthesizing initial hotplug events

Setting the hostname to aigo_R&D

Mounting filesystems

initrd-cpio无法启动:

Kernel command line: root=/dev/ram rw console=ttymxc0,115200

checking if p_w_picpath is initramfs...it isn't (out of input data); looks like an initrd

Freeing initrd memory: 2376K

RAMDISK: Compressed p_w_picpath found at block 0

RAMDISK: ran out of compressed data

out of input data

List of all partitions:

1f00 2048 mtdblock0 (driver?)

1f01 4096 mtdblock1 (driver?)

1f02 2048 mtdblock2 (driver?)

1f03 16384 mtdblock3 (driver?)

1f04 8192 mtdblock4 (driver?)

1f05 4096 mtdblock5 (driver?)

1f06 786432 mtdblock6 (driver?)

1f07 3371008 mtdblock7 (driver?)

No filesystem could mount root, tried: ext2 cramfs vfat msdos

Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0)


initrd的解压:

  • 2.6之前的格式使用:

gunzip initrd.gz

mount -o loop initrd /mnt/something


  • 2.6内核中的initrd.img采用cpio压缩,不再是2.4内核使用的ext2格式,无法使用mount -o loop 挂载。需要使用gunzip解压缩,然后再使用cpio解包

cp /boot/initrd-***.img initrd.img.gz
gunzip initrd.img.gz
mkdir initrd
mv initrd.img initrd
cd initrd
cpio -ivmd < initrd.img

通过以上命令就将initrd.img解压了,现在就可以对其进行编辑,完成后使用以下命令重新压制

find . | cpio -ov > ../initrd.new.img
gzip ../initrd.new.img

再将其改名拷贝至/boot目录,重启就可以观察修改后的效果


参考资料:

Linux文档中关于ramdisk的介绍,核心目录里 Documentation/ramdisk.txt;

Linux文档中关于initrd的介绍,核心目录 Documentation/initrd.txt;

Linux文档中关于tmpfs的介绍,核心目录 Documentation/filesystems/tmpfs.txt;

参考:

Linux2.6 内核的 Initrd 机制解析