一、 Ramdisk

RamDisk 就是将内存中的一块区域作为物理磁盘来使用的一种技术。使用时内核配置:两个选项:第一个设定Ramdisk个数,默认16个;第二个是设定Ramdisk的大小,设定16M

Device Drivers —>
[*] Block devices —>
<*> RAM block device support
(16) Default number of RAM disks
(16384) Default RAM disk size (kbytes)

另外:

设置initramfs/initrd的支持

General setup —>
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support

二、 initrd

initrd全称是 initial RAM disk ,它提供一种让Kernel可以简单使用Ramdisk的能力,简单的说,这些能力包括:
格式化一个Ramdisk;
加载文件系统内容到Ramdisk;
将Ramdisk作为根文件系统;

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

initrd支持的格式
· Romfs文件系统;
· Ext2文件系统;
· cramfs文件系统;
· minix文件系统;

三、Gzip支持

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

四、制作initrd

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

办法一:
通过ramdisk来制作的方法比较简单(以ext2文件系统为例):

# mkfs.ext2 /dev/ram0
# mount /dev/ram0 /mnt/rd
# cp _what_you_like_ /mnt/rd # 把需要的文件复制过去
# dd if=/dev/ram0 of=/tmp/initrd
# gzip -9 /tmp/initrd

这个过程也最能够解释initrd的本质,对于Linux来说,Ramdisk的一个块设备,而initrd是这个块设备上所有内容的“克隆”(由
命令dd来完成)而生成的文件。核心中加载initrd相关的代码则用于完成相反的过程,即将这一个文件恢复到Ramdisk中去。

办法二:

通过loop设备来制作initrd的过程:

# dd if=/dev/zero of=/tmp/initrd bs=1024 count=4096 # 制作一个4M的空白文件
# losetup /dev/loop0 /tmp/initrd # 映射到loop设备上;
# mkfs.ext2 /dev/loop0 # 创建文件系统;
# mount /dev/loop0 /mnt/rd
# cp _what_you_like_ /mnt/rd # 复制需要的文件;
# umount /mnt/rd
# losetup -d /dev/loop0
# 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-image可以成功启动log:

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

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

Freeing initrd memory: 2402K

RAMDISK: Compressed image 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 image is initramfs...it isn't (out of input data); looks like an initrd

Freeing initrd memory: 2376K

RAMDISK: Compressed image 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和initramfs的区别

原文:https://www.linux.com/learn/linux-training/92607-the-kernel-newbie-corner-qinitrdq-and-qinitramfsq-whats-up-with-that

initrd:initial ramdisk
initramfs:initial ram filesystem

Linux内核在初始化之后会执行init进程,而init进程会挂载我们的根文件系统,但由于init程序也是在根文件系统上的,所以这就有了悖论。Linux采用两步走的方法来解决这个问题。Linux2.6版以前的方法是:除了内核vmlinuz之外还有一个独立的initrd.img映像文件,其实它就是一个文件系统映像,linux内核在初始化后会mount initrd.img作为一个临时的根文件系统,而init进程就是在initrd.img里的,然后init进程会挂载真正的根文件系统,然后umount initrd.img。但Linux2.6内核的实现方式却不太一样,虽然完成的功能是一样的。Linux2.6采用initramfs。initramfs:init ram filesystem,它是一个cpio格式的内存文件系统,制作的方法有两个,一个是http://blog.csdn.net/htttw/article/details/7215858介绍的,但这样做出来的initramfs是和内核vmlinuz分开的,因此我们需要在grub里写上initramfs的路径。而另一种方法是把内核和initramfs制作在一起成为一个文件,方法是在linux源码make menuconfig,然后General setup-->选择Initial RAM filesystem and RAM disk (initramfs/initrd) support,然后在Initramfs source file(s)里输入我们的initramfs目录,然后make bzImage。这种方法做出来的内核就只有一个文件,不需要指定initramfs了。

下面我们依次介绍:
实验一:制作传统的initrd

1.
静态编译Busybox,生成_install目录,具体编译方法参考:http://blog.csdn.net/htttw/article/details/7215858的前半部分

2.
mkdir ~/ramdisk
cd ramdisk
首先创建一个映像,他就是最终的initrd:
dd if=/dev/zero of=ramdisk bs=1k count=8000
以上命令创建一个8M的ramdisk映像

3.
然后格式化成ext3格式:
mkfs.ext2 -j ramdisk
然后按“y”

4.
然后挂载:sudo mount ramdisk /mnt -o loop

5.
然后复制busybox下的_install目录到/mnt下
sudo cp -R busybox/_install /mnt

6.
然后创建必要的目录,后面就和http://blog.csdn.net/htttw/article/details/7215858的“上面只是准备工作,下面才开始好玩了”后面是一样的,一直到创建init链接:ln -sv bin/busybox init之后
注意:现在我们所有的操作都是在/mnt里进行的,即在第二步生成的ramdisk里

6.
卸载ramdisk:
sudo umount /mnt

7.
copy到/boot下,准备测试
sudo cp ramdisk /boot/ramdisk

8.重启,进入grub命令模式,指定linux和initrd进行测试,具体参考:http://blog.csdn.net/htttw/article/details/7215858的最。如果一切顺利,最后我们会进入Busybox。

实验二:制作现代的initramfs:
上面说过了,制作现代的initramfs有两种方法,第一种就是http://blog.csdn.net/htttw/article/details/7215858介绍的,下面介绍第二种,即在make menuconfig里指定:

1.准备好_install目录,然后创建必要的文件,假设是ramfs目录

2.在make menuconfig里指定Initramfs source file(s)的路径是第一步的ramfs,然后重新编译内核:make bzImage

3.测试,和上面方法是一样的,不过不用指定initrd了,因为内核和initramfs是编译在一起的,最后我们会进入Busybox。
这里插一句,我们完全可以自己写init进程,只要替换_install目录里的init就可以了~~
另外,这里多加一个小实验,模拟ramfs的挂载与卸载过程:
首先准备好一个busybox的ramdisk,我们把它作为真正的根文件系统
然后把它copy到我们自己做的ramfs的/root/下,并修改ramfs的etc/init.d/rcS如下:

#!/bin/sh
mount -a
mount /root/ramdisk /mnt
exec switch_root /mnt /sbin/init

这样最终就mount进我们的根文件系统里了。