LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1895|回复: 14

使用ram disk初始化(initrd)

[复制链接]
发表于 2006-2-21 17:38:57 | 显示全部楼层 |阅读模式
使用ram disk初始化(initrd)

================================

Written 1996,2000 by Werner Almesberger <werner.almesberger@epfl.ch> and
                     Hans Lermen <lermen@fgan.de>

翻译:szs<good02xaut@hotmail.com>

                     
initrd提供了在boot loader下加载ram disk的方法。该ram disk可以被作为根文件系统挂载进来,里面的程序也可以运行。然后,新的根文件系统可以从其他设备挂载。之前的根(来自initrd)可以被转移到一个目录然后被卸载。



initrd主要设计用来使系统启动于两个条件,一个[color="Red"]是内核来自于非常小的驱动器,一个[color="red"]是额外的模块需要从initrd中加载



本文给出initrd的概要描述,更具体的可以参考[1]。



操作

-------

当使用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文件系统被移去。

   

注意,改变根目录不牵扯卸载他。

挂载在initrd的文件系统仍然可以被访问。



启动命令选项

------------------------

initrd添加了如下新的选项:

   initrd=<path>    (e.g. LOADLIN)   

   加载特定的文件作为初始的ram disk。当使用lilo,你应该在/etc/lilo.conf中指定

   ram disk镜像文件位置,使用INITRD变量。

   

   noinitrd   

   initrd数据被保留却不转化成ram disk,正常的根文件系统被加载。initrd的数据可以   从/dev/initrd中读取。注意,在initrd中的数据可以是任意结构的,不一定要是文件系统镜像。该选项多用于调试。

   

   注意:/dev/initrd是只读的,而且只能被使用一次。只要最后一个进程关闭它,所有的数据将会释放掉,而/dev/initrd将不再被打开。

   

   root=/dev/ram0   (without devfs)
   root=/dev/rd/0   (with devfs)

   

   initrd作为根文件系统被挂载,随后正常的启动顺序中,ram disk 仍然作为root。

   

安装

------------

首先,用于initrd文件系统的目录在根文件系统上被创建:

#mkdir /initrd



名字不是很重要。更多的可以参考pivot_root(2)的man。



在启动过程中,如果根文件系统被创建(如果你有软盘启动),那么根文件系统应该创建/initrd目录。



如果initrd没有被挂载,他里面的内容仍然可以被访问,通过以下的方法(注意,这在使用devfs时不可用):

# mknod /dev/initrd b 1 250
# chmod 400 /dev/initrd



第二步,内核编译的时候必须支持ram disk并启动ram disk使能。所有从initrd中执行的程序必须被编译到内核中。



第三步,你必须创建ram disk镜像。这可以通过在块设备上创建文件系统实现,把所需的文件拷贝,然后把文件拷贝到initrd文件。根据最新的内核,至少三种设备可以用:

l         软盘(慢,却随处可用)

l         ram disk(快,需要物理内存)

l         loopback device(最高档)

   

我将介绍loopback device方法:

保证loopback device被内核支持

创建一个空的文件系统,拥有合适的大小:

     # dd if=/dev/zero of=initrd bs=300k count=1
     # mke2fs -F -m0 initrd

    如果空间不多,你可以用minix fs而不是ext2

挂载文件系统

      # mount -t ext2 -o loop initrd /mnt

创建控制台设备(如果用devfs,就没必要)

      # mkdir /mnt/dev
      # mknod /mnt/dev/console c 5 1

拷贝initrd环境需要的所有文件。不要忘掉最重要的文件/linuxrc.

注意,/linuxrc必须有执行权限。

正确的initrd环境可以不用重启就可以通过命令行测试:

  # chroot /mnt /linuxrc

卸载文件系统

     # umount /mnt

现在initrd被保存在initrd文件中。还可以压缩他。

     # gzip -9 initrd

为了试验initrd,你可以创建一个急救盘,只需创建/linuxrc到/bin/sh的符号链接。

你还可以试着把initrd更小。



最后,你要启动内核并加载initrd.几乎所有的boot loader都支持initrd.  

虽然启动进程兼容老的机制,下面的启动命令行还是得给出:

   

   root=/dev/ram0 init=/linuxrc rw
如果不使用devfs.或者

  root=/dev/rd/0 init=/linuxrc rw

如果使用devfs.



使用 LOADLIN,只要执行

       LOADLIN <kernel> initrd=<disk_image>
e.g. LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0
       init=/linuxrc rw

      

使用LILO,你添加选项INITRD=<path>到/etc/lilo.conf中,使用APPEDN命令即可。

    image = /bzImage
    initrd = /boot/initrd.gz
    append = "root=/dev/ram0 init=/linuxrc rw"

然后运行 /sbin/lilo



对于其他的启动程序,请参考相应的文档。



现在你可以启动并享受使用initrd的乐趣了



如何改变根设备

------------------

当完成他的任务,linuxrc改变根设备并启动真正的根设备。



整个过程包括如下几步:

1.       挂载新的根文件系统

2.       把他变成根文件系统

3.       删除所有对旧(Initrd)文件系统的访问

4.       卸载initrd文件系统,重定位ram disk



挂载新的根文件系统很容易:只需把他挂载到当前根下。例如:

# mkdir /new-root
# mount -o ro /dev/hda1 /new-root



根的转变伴随着pivot_root系统调用。pivot_root把当前的根转移到新根下的一个目录,并把新的根放到原来的地方。老根的目录必须在调用pivot_root前退出。例如:

# cd /new-root
# mkdir initrd
# pivot_root . initrd



现在,linuxrc进程可以仍然访问老的根。所有的这些引用可以通过如下命令释放:

# exec chroot . what-follows <dev/console >dev/console 2>&1



然后执行的就是新根下的,例如/sbin/init.

如果新的根文件系统使用devfs,而/dev目录还不可用,devfs必须被挂载进来,

在使用chroot之前,只有这样才有/dev/console设备。



注意:privot_root执行的情况可能有所不同。为了保证兼容性,注意以下几点:调用pivot_root之前,调用进程的当前目录应指向新的根文件目录使用.作为第一个参数,老根的相对路径作为第二个参数。chroot程序必须在就老的和新的根下都可以使用。最后改变根到新的根下。在执行命令中使用dev/console的相对路径。





注意,initrd可以被卸载,而ram disk使用的内存可以被释放:

# umount /initrd
# blockdev --flushbufs /dev/ram0    # /dev/rd/0 if using devfs



initrd还可以使用NFS-mounted根,参考man pivot_root(8)。



注意:如果linuxrc或者其他程序从终端执行,老的改变根机制必须调用。



使用限制

-----------

引入initrd的主要动机是为了在系统安装中可以模块化配置内核。过程运行如下:

1.       一个小内核的系统从软盘或其他介质上启动(支持ram disk,initrd,a.out, ext2fs),并加载initrd。

2.       /linuxrc决定如何挂载真正的根文件系统(设备类型,设备驱动,文件系统),并分布媒体(CDROM,network,tape)。这些可以询问用户或者自动探测,或是混合使用。

3.       /linuxrc加载必须的内核模块

4.       /linuxrc创建并组装根文件系统(还不一定能用)。

5.       /linuxrc调用pivot_root改变根文件系统,执行(chroot)安装程序.

6.       boot loader 安装完毕

boot loader配置用于加载initrd,initrd中包含系统启动的必须模块。

现在系统可以启动的,额外的安装任务被执行。



initrd的主要任务是在正常的系统操作中复用配置数据,而不需重新编译链接内核。



第二个限制是在linux运行在不同的硬件配置上的安装问题。这种情况下,只需产生一个小内核,分别配置。initrd中必须含有所有需要的模块。然后,/linuxrc或其他一个文件可能有所不同。



第三个限制更方便恢复磁盘,因为象根文件系统分区的信息在系统启动的时候要用,而在启动时刻是得不到的。



最后,CDROM发布使他更方便安装。



荒废的根改变机制

----------------

下面的机制在pivot_root之前被使用。当前的内核仍然支持他,但是你不要依赖他。



他在linuxrc存在的情况下,把真正的根设备作为根文件系统。initrd文件系统然后被

卸载,或者把他移动到/initrd目录,如果这个目录存在于新的根文件系统。



为了使用这种机制,你不必设定启动参数root,init,rw(如果设定了,这将影响到真正的

根文件系统)。

==========================================
[color="Red"]这是我从前的译文,之所以贴出来,是在硬盘安装LFS中牵扯到了initrd这个东东。
initrd-2.6.12.img这种映象文件很常见,grub启动时通过initrd加载
其实这个映象文件中使用的文件系统却是ext2。
分清2个概念:ramdisk,和initrd。
ramdisk是个硬件,相当于一个磁盘,无非是从内存虚拟出来的。
initrd是个压缩的文件系统映象,是个软件概念。

liveCD很奇怪的使用了2.6新出的ramfs,这是一种文件系统和ext2一样。说明liveCD的/boot/isolinux/linuxz并不支持ext2,所以无法使用从前的initrd映象格式。
linuxz是不是把对ext2的支持编译成了模块,并且放到了initramfs_data_cpio.gz的这个文件系统中呢。如果是,linuxz就可以支持挂载ext2分区的!

从Initrd的2个功能(粗体加强)可以看出,这里很可能用到了额外的模块需要从initrd中加载,他就是ext2。

大家一起分析一下initramfs_data_cpio有什么作用,看看到底是如何工作的。
发表于 2006-2-21 18:07:39 | 显示全部楼层
好,我终于可以自己做 initrd 了.

现在的问题就是必须在里面加上 udev
回复 支持 反对

使用道具 举报

发表于 2006-2-21 18:31:33 | 显示全部楼层
你是说把 udev 加在 initrd 里边?这样 initrd 里边就可以包含大多数的设备文件,但是不过是否齐全呢?

我有一个非常基础的问题:initrd 里边东西,是在哪里执行的?就是说是内核完全驱动完后,然后进入 initrd,再通过pivot_root 进去主系统的,是不是这样?
回复 支持 反对

使用道具 举报

发表于 2006-2-21 19:47:12 | 显示全部楼层
把 udev 加在 initrd 里边?这样的意义何在?

关於initrd在启动时如何加载根文件系统,以前日月教主两篇关於initrd的大作也很详细

http://www.linuxsir.cn/bbs/showthread.php?t=184629
http://www.linuxsir.cn/bbs/showthread.php?t=113586
回复 支持 反对

使用道具 举报

发表于 2006-2-21 20:31:02 | 显示全部楼层
Post by d00m3d
把 udev 加在 initrd 里边?这样的意义何在?



这样可以在initrd中直接加载硬件设备,比如检测出硬盘,然后加载一些模块.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-2-21 20:31:53 | 显示全部楼层
不是udev的问题,是initramfs里面的那个init文件有问题
liveCD的文档有init.c的内容,一看就不合适用,重做一个init,应该就可以了。
回复 支持 反对

使用道具 举报

发表于 2006-2-21 20:42:05 | 显示全部楼层
若如此,何不取消使用initrd让系统直接启动?
回复 支持 反对

使用道具 举报

发表于 2006-2-21 21:32:26 | 显示全部楼层
http://www.knoppix.net/forum/viewtopic.php?t=22271

initRD vs initRAMFS:
initRAMFS is, as it's described in the kernel documentation, 'a chunk of code that unpacks the compressed cpio image midway through the kernel boot process.' The files contained within that image are then used to populate the root filesystem. Initramfs is a part of a bigger concept called 'early-userspace'. It's described in detail in <kernel-sources>/Documentation/early-userspace/. The general idea is "if it can be kept out of the kernel, let it stay that way".

I'm not going into any huge debate about the pros and cons of these two but one thing I will mention is that initRD is old generation and there are plans to supersede it. "With what?" you ask. Currently there are two options being looked at that I know of, one is yaird (name speaks for itself) and the other is initramfs (which I will be talking about here). If you want to know more try Google but for now there is a Debian comparison available at http://wiki.debian.org/InitrdReplacementOptions
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-2-21 21:44:41 | 显示全部楼层

通常不用Initrd的

Post by d00m3d
若如此,何不取消使用initrd让系统直接启动?

一般我都用noinitrd作为内核参数

坏在那个liveCD的kernel不支持该支持的文件系统,需要用initrd帮助提供扩充功能!
回复 支持 反对

使用道具 举报

发表于 2006-2-22 09:34:40 | 显示全部楼层
用 initrd 可以缩小 kernel 体积,除了 initrd 的 fs ,别的 fs都可以用modules.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表