您的位置:首页 > 运维架构 > Linux

嵌入式Linux中initrd的应用--浅析ramdisk、ramfs、initrd和initramfs

2013-09-11 15:30 197 查看


嵌入式Linux中initrd的应用--浅析ramdisk、ramfs、initrd和initramfs

http://blog.linux.org.tw/~jserv/archives/001954.html

/article/5083988.html

http://blog.chinaunix.net/uid-488742-id-2113871.html

http://blog.chinaunix.net/uid-25888519-id-3078218.html

在Essential Linux.Device Drivers里看到这样一句话

在嵌入式系统开发过程中, initrd 和 initramfs 有时候也可被用作嵌入式设备上实际的根文件系统。

看到这样的一句话很让我费解,因为似乎我理解为这样做能够提高一点嵌入式linux启动速度,我对此是非常地感兴趣

自此,就开始了我的解惑之旅

首先需要知道的是ramdisk和ramfs

http://www.linuxfordevices.com/c/a/Linux-For-Devices-Articles/Introducing-initramfs-a-new-model-for-initial-RAM-disks/

或者内核源码/Documentation/filesystems/ramfs-rootfs-initramfs.txt

从上述文章,大致可以了解到 ramdisk是一种基于ram的块设备,ramfs是一种基于ram的文件系统,开发ramfs的目的是因为ramdisk浪费了太多的内存cache页,ramfs是基于tmpfs的一个实例

顺理成章,initrd是init ramdisk的缩写,initramfs是init ramfs的缩写

名称里加了init前缀,代表它们具有了引导内核启动的功能

ramfs比ramdisk更加高效,自然initramfs也更加优秀,是2.6内核新加入的推荐使用的机制,虽然可能pc中grub使用的内核cmd line参数是

kernel /vmlinuz-2.6.25-14.fc9.i686 ro root=UUID=11d7ac51-2b45-489e-8a48-8d2a28e2c04e rhgb quiet

initrd /initrd-2.6.25-14.fc9.i686.img ,实际上使用的是initramfs,可以靠文件格式来区分。initrd是gziped的,initramfs是cpio的

剩下的部分就只说initrd了

首先是initrd的作用:内核镜像要尽可能小,所以不应该静态包含进太多驱动模块。但是Linux内核启动最后一步,创建init内核线程,需要执行的init程序或者脚本并不在内核镜像中,而在根文件系统中。根文件系统可能在硬盘、磁盘阵列、nfs、flash上,同时根文件系统的格式也是五花八门。此时,实在不想包含这么多驱动到镜像的话,可以使用initrd作为一个过渡。

initrd本身的内容就是一个精简的根文件系统,包含必备的目录和程序,甚至也有一个init脚本或程序linuxrc

一切的一切,因为linux的高可定制性,一切随你便。在pc上通常是后者

以pc上的为例,首先拷贝一个initrd-2.6.25-14.fc9.i686.img,防止破坏了它开不了机

然后将其备份改名为gz,解压缩

[root@localhost boot]# mkdir /tmp/initrd

[root@localhost boot]# cp initrd-2.6.25-14.fc9.i686.img /tmp/initrd/

[root@localhost boot]# cd /tmp/initrd/

[root@localhost initrd]# mv initrd-2.6.25-14.fc9.i686.img initrd-2.6.25-14.fc9.i686.gz

[root@localhost initrd]# gunzip initrd-2.6.25-14.fc9.i686.gz

[root@localhost initrd]# ls

initrd-2.6.25-14.fc9.i686

[root@localhost initrd]# file initrd-2.6.25-14.fc9.i686

initrd-2.6.25-14.fc9.i686: ASCII cpio archive (SVR4 with no CRC)

继续解压缩,查看其根目录下的init脚本,其重要的地方都用加粗了

#!/bin/nash

mount -t proc /proc /proc

setquiet

echo Mounting proc filesystem

echo Mounting sysfs filesystem

mount -t sysfs /sys /sys

echo Creating /dev

mount -o mode=0755 -t tmpfs /dev /dev

mkdir /dev/pts

mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts

mkdir /dev/shm

mkdir /dev/mapper

echo Creating initial device nodes

mknod /dev/null c 1 3

mknod /dev/zero c 1 5

mknod /dev/systty c 4 0

mknod /dev/tty c 5 0

mknod /dev/console c 5 1

mknod /dev/ptmx c 5 2

mknod /dev/tty0 c 4 0

mknod /dev/tty1 c 4 1

mknod /dev/tty2 c 4 2

mknod /dev/tty3 c 4 3

mknod /dev/tty4 c 4 4

mknod /dev/tty5 c 4 5

mknod /dev/tty6 c 4 6

mknod /dev/tty7 c 4 7

mknod /dev/tty8 c 4 8

mknod /dev/tty9 c 4 9

mknod /dev/tty10 c 4 10

mknod /dev/tty11 c 4 11

mknod /dev/tty12 c 4 12

mknod /dev/ttyS0 c 4 64

mknod /dev/ttyS1 c 4 65

mknod /dev/ttyS2 c 4 66

mknod /dev/ttyS3 c 4 67

echo Setting up hotplug.

hotplug

echo Creating block device nodes.

mkblkdevs

echo "Loading ehci-hcd module"

modprobe -q ehci-hcd

echo "Loading ohci-hcd module"

modprobe -q ohci-hcd

echo "Loading uhci-hcd module"

modprobe -q uhci-hcd

mount -t usbfs /proc/bus/usb /proc/bus/usb

echo "Loading ext3 module"

modprobe -q ext3

echo "Loading scsi_mod module"

modprobe -q scsi_mod

echo "Loading sd_mod module"

modprobe -q sd_mod

echo "Loading libata module"

modprobe -q libata

echo "Loading ata_generic module"

modprobe -q ata_generic

echo "Loading pata_acpi module"

modprobe -q pata_acpi

echo Waiting for driver initialization.

stabilized --hash --interval 250 /proc/scsi/scsi

echo "Loading ata_piix module"

modprobe -q ata_piix

echo Waiting for driver initialization.

stabilized --hash --interval 250 /proc/scsi/scsi

echo "Loading dm-mod module"

modprobe -q dm-mod

echo "Loading dm-mirror module"

modprobe -q dm-mirror

echo "Loading dm-zero module"

modprobe -q dm-zero

echo "Loading dm-snapshot module"

modprobe -q dm-snapshot

echo Making device-mapper control node

mkdmnod

modprobe scsi_wait_scan

rmmod scsi_wait_scan

mkblkdevs

echo Scanning logical volumes

lvm vgscan --ignorelockingfailure

echo Activating logical volumes

lvm vgchange -ay --ignorelockingfailure VolGroup00

resume /dev/VolGroup00/LogVol01

echo Creating root device.

mkrootdev -t ext3 -o defaults,ro /dev/VolGroup00/LogVol00

echo Mounting root filesystem.

mount /sysroot

echo Setting up other filesystems.

setuproot

loadpolicy

echo Switching to new root and running init.

switchroot

echo Booting has failed.

sleep -1

首先,这里使用的是nash,不是bash、csh等常见shell。nash是专门为了init设计的,因为体积小。

pc机上的initrd不过只是一个过渡,所以在加载完了硬盘、ext3等驱动后,就迫不及待地要重新设置根文件系统了

首先mkrootdev指定最终的根目录,参数跟grub的内核启动参数一致。接着mount /sysroot将最终的根目录先挂在到/sysroot ,setuproot开始将initrd中的/proc /dev /sys 中的资料转移到 /sysroot ,

switchroot会开始转换/sysroot 为最终的根文件系统,完成后顺便将initrd之前在ram中的一切清空。

(如果有/initrd 目录的话就会把initrd挂载到该目录下)

好了,扯了半天,终于能解释最开始的疑惑了

initrd,或者initramfs,无论在pc还是嵌入式,都是可以选择的,分3种情况

1 完全不要initrd

2 initrd作为最终的根文件系统

3 initrd作为过渡,由initrd的init来加载最终的根文件系统

(本文作者deep_pro http://hi.baidu.com/deep_pro/ 转载请注明出处)

情况1,比如嵌入式linux静态包含了nand flash驱动和jffs2驱动,指定内核启动参数

root=/dev/mtdblock2 rootfs=jffs2 rw console=ttySAC0,115200 init=/linuxrc

(使用busybox作为根文件系统)

情况2,将根文件系统做成ramdisk镜像,使用ubbot下载到0x30800000,内核启动参数

root=/dev/ram rw init=/linuxrc initrd=0x30800000,8M console=ttySAC0,115200

注意,一旦使用了ramdisk作为内核命令行参数root的参数,root=/dev/ram

那么就直接把 initrd当做最终的根文件系统

情况3,pc常见,嵌入式linux也可见这样的启动参数

console=ttySAC0,115200 root=nfs nfsroot=192.168.1.9:/source/rootfs initrd=0x10800000,0x14af47

也属于情况3

对于arm平台,如果bootloader不支持装入initrd的话,可以使用bootpImage,这种复合镜像会把内核和initrd直接连接到一起。

现在看来,initrd作为最终的根文件系统,将花费时间将initrd从flash读入ram,同时对文件系统的读写不会写入falsh

完全不要initrd,根文件系统一直存在于flash,如果根文件系统可写,也将写入flash

至于性能上的比较,还是经验不足啊
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: