一 RAMDISK VS INITRD
先简单介绍一下ramdisk,Ramdisk是虚拟于RAM中的盘(Disk)。对于用户来说,可以把RAM disk与通常的硬盘分区(如/dev/hda1)同等对待来使用
# mkfs.ext2 /dev/ram0
# mount /dev/ram0
# mkdir /mnt/rd
# mount /dev/ram0 /mnt/rd
# ls /mnt/rd
lost+found
# df -h /dev/ram0
编译到核心时,可以通过下面的一些核心命令行参数来配置Ramdisk:
ramdisk_size - ramdisk的大小(Kbytes);
initrd概述
上面已经提到,Ramdisk需要先格式化然后理能使用。那么,如果核心希望使用ramdisk该如何做呢?于是initrd产生了,initrd全称是 initial RAM disk ,它提供一种让核心可以简单使用Ramdisk的能
力,简单的说,这些能力包括:
格式化一个 Ramdisk;
加载文件系统内容到Ramdisk;
将Ramdisk作为根文件系统;
我们可以将initrd形像的比作Norton Ghost备份的硬盘分区,而Linux启动阶段的Ramdisk相当于一个未格式化的硬盘分区,核心可以直接将initrd的内容释放到一个未初始化的Ramdisk里,这个过程与
Ghost恢复一个分区的过程十分相似。于是,相应的内容被加载到相应的Ramdisk中,同时,这个Ramdisk也被格式化成某种由initrd格式所表达的分区格式。
initrd与Ghost备份的分区有许多相似之处,例如,它有一定的大小,包含分区上的文件系统格式等。initrd支持的格式包括:
Ext2文件系统;
Romfs文件系统;
cramfs文件系统;
minix文件系统;
1)传统方法制作initrd
# 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文件就是ext2格式的盘,当它释放到没有格式的ramdisk的时候,ramdish自然被格式化成ext2格式的盘了,这个格式是由initrd决定的。)
这个过程也最能够解释initrd的本质,对于Linux来说,Ramdisk的一个块设备,而initrd是这个块设备上所有内容的“克隆”(由命令dd来完成)而生成的文件。核心中加载initrd相关的代码则用于完
成将相反的过程,即将这一个文件恢复到Ramdisk中去。
2)通过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
3)另外使用loop设备制作initrd的过程
# dd if=/dev/zero of=/tmp/initrd bs=1024 count=4096 # 制作一个4M的空白文件
# mkfs.ext2 /tmp/initrd
# mount /tmp/initrd /mnt/rd -t ext2 -o loop=/dev/loop0
# cp _what_you_like_ /mnt/rd # 复制需要的文件;
# umount /mnt/rd
# gzip -9 /tmp/initrd
(由此可见,loop就是一个设备文件,initrd必须和设备文件绑定或映射或等同,才进行近一步的操作。mount可分解成losetup /dev/loop0 /tmp/initrd and mount /dev/loop0 /mnt/rd)
使用ram disk初始化(initrd)
initrd提供了在boot loader下加载ram disk的方法。该ram disk可以被作为根文件系统挂载进来,里面的程序也可以运行。然后,新的根文件系统可以从其他设备挂载。之前的根(来自initrd)可以被
转移到一个目录然后被卸载。
initrd主要设计用来使系统启动于两个条件,一个是内核来自于非常小的驱动器,一个是额外的模块需要从initrd中加载。
当使用initrd,典型的系统启动顺序如下:
1. boot loader加载内核并初始化ram disk
2. 内核把initrd转化成正常的ram disk 并释放initrd使用的内存
3. initrd作为root被挂载,赋予读写权限。
4. /linuxrc被执行(这可以是任何可执行文件,如脚本,运行在uid 0,可以做任何初始化)。
5. linuxrc挂载真正的根文件系统
6. linuxrc使用pivot_root系统调用把根文件系统放在根目录。
7. 正常的启动序列(/sbin/init)在根文件系统上执行。
8. initrd文件系统被移去。
二 RAMFS VS TMPFS vs ramdisk vs initramfs
1.ramdisk是由块设备来实现的,必须格式化成某种文件格式才能使用,需要设备文件,例如ram0等,initrd就是initial ramdisk;编译内核时须将block device中的Ramdisk支持选上,它下面还有两个
选项,一个是设定Ramdisk的大小,默认是4096k;另一个是initrd的支持。其不足之处是大小固定,之后不能改变。
2.ramfs就是内存文件系统,不需要格式化,不需要设备文件,可以动态增长;
3.tmpfs是虚拟内存文件系统,它不同于传统的用块设备形式来实现的ramdisk,也不同于针对物理内存的Ramfs,Tmpfs可以使用物理内存,也可以使用交换分区。在Linux内核中,虚拟内存资源由物理内
存(RAM)和交换分区组成,这些资源是由内核中的虚拟内存子系统来负责分配和管理。 Tmpfs就是和虚拟内存子系统来"打交道"的,它向虚拟内存子系统请求页来存储文件,它同Linux的其它请求页的
部分一样,不知道分配给自己的页是在内存中还是在交换分区中。Tmpfs同Ramfs一样,其大小也不是固定的,而是随着所需要的空间而动态的增减。使用tmpfs,首先你编译内核时得选择"虚拟内存文件
系统支持(Virtual memory filesystem support)" ,然后就可以加载tmpfs文件系统了。
4.rootfs是ramfs的特殊实例, 在2.6的内核中必然存在。rootfs不能被卸载(与其添加特殊代码用来维护空的链表,不如把rootfs节点始终加入,因此便于kernel维护:简单、精炼。rootfs是ramfs的一
个空实例,占用空间极小)。大部分其他的文件系统安装于rootfs之上。
5.initramfs:2.6的Linux内核包含有gzip压缩的cpio格式的文档,可以在内核引导的时候解压缩为rootfs
6.补充:通常情况下,Linux的所有文件在内存中都有缓存。需要读取的数据页从支撑存储设备(block
device)中读取后,缓存于内存。在支撑存储设备中的数据页执行marked as
clean操作。当虚拟文件系统需要支撑存储设备中的数据页内存时,可以释放。基于同样的机制,支撑存储设备的写入操作(写入文件然后写回支撑存储设
备,marked as clean)后,也可以释放占用的数据页内存。对于文件目录占用的缓存(dentry: directory
entry),也存在同样的机制。但是,ramfs中不需要支撑存储设备(没有支撑缓存,但是有缓存)。也就是说,写入ramfs的文件可以正常的分配
page cache and dentry cache,但是不能写入支撑存储设备。这些page cache and dentry
cache不能被VM释放、回收。由于ramfs可以基于现有的Linux的文件系统结构,用于实现ramfs的代码很小。一般而言,支撑存储设备的缓存
被安装为一个文件系统。所以,ramfs不能通过menuconfig选择,是必然进入内核的。在
ramfs的下面可以一直写入数据,直到写满内存为止。由于VM(Vitual
Memory)认为文件应该被写回支撑存储设备,而不是交换空间(swap
space),所以VM不能释放ramfs分配的内存。从而,只有root用户(or trusted user)才能进行ramfs写操作。
例1
# mkdir -p /RAM1
# mount -t ramfs none /RAM1
例2
# mkdir -p /RAM1
# mount -t ramfs none /RAM1 -o maxsize=10000
例3
# mkdir -p /mnt/tmpfs
# mount tmpfs /mnt/tmpfs -t tmpfs
例如4
# mount tmpfs /mnt/tmpfs -t tmpfs -o size=32m
三 initrd vs initramfs
1. initrd是一个单独的文件;initramfs和Linux内核链接在一起(/usr目录下的程序负责生成initramfs文档)。
2. initrd是一个压缩的文件系统映像(可以是ext2等,需要内核的驱动);initramfs是类似tar的cpio压缩文档。内核中的cpio解压缩代码很小,而且init数据在boot后可以丢弃。
3. initrd运行的程序(initd,不是init)进行部分setup后返回内核;initramfs执行的init程序不返回内核(如果/init需要向内核传递控制权,可以再次安装在/目录下一个新的root设备并且启动一个新
的init程序)。
4. 切换到另一个root设备时,initrd执行pivot_root后,卸载ramdisk;initramfs是rootfs,既不能
pivot_root,也不能卸载。initramfs会删掉rootfs的所有内容(find -xdev / -exec rm '{}' ';')
,再次安装root到rootfs(cd /newmount; mount --move . /; chroot
.),把stdin/sdout/stderr挂在新的/dev/console上,重新执行init。由于这是一个相当困难的实现过程(包括在使用一个
命令之前
把它删除),所以klibc工具包引入一个帮助程序/utils/run_init.c来执行上述过程。其他大部分工具包(包括busybox) 把这个命令称为"switch_root"。
问题:
在嵌入式中,rootfs即initramfs就是最终的根文件文件系统,是不是说这个根也是ramfs文件系统呢,没有和设备绑定的?命令行用到ram0,但ram0不是和ramdisk相关的嘛,如下
# cat cmdline
console=ttyS1,57600n8 root=/dev/ram0
# mount
rootfs on / type rootfs (rw)
proc on /proc type proc (rw)
none on /var type ramfs (rw)
none on /etc type ramfs (rw)
none on /tmp type ramfs (rw)
none on /media type ramfs (rw)
none on /sys type sysfs (rw)
none on /dev/pts type devpts (rw)
none on /proc/bus/usb type usbfs (rw)
mdev on /dev type ramfs (rw)
devpts on /dev/pts type devpts (rw)
阅读(2786) | 评论(0) | 转发(0) |