Next Previous Contents

3. 如何建立绕回根目录设备

下面将介绍如何建立绕回设备

3.1 需求

要建立一个绕回根目录设备必须要有下列事项.

最重要的是必须能存取一个安装好可运作的 Linux 系统. 这是因为绕回设备只能在 Linux 下建立. 也就是说你不可能从无中生有. 而且你必须要能在这个系统上编译核心.

当绕回设备建立之后, 这将是一个很大的文档. 我使用了一个 80 MB 的文档, 如此我才能建立一个 X 终端机; 但如果你希望能做更多事, 这可能也不够. 这个文档必须被复制到 DOS 分割区中, 所以网路或是一堆软盘是必须的.

你所需要的软件包括:

对现在的 Linux 而言, 应该都能符合以上需求.

3.2 建立 Linux 核心

我是用 2.0.31 版的核心来使用绕回装置, 其他版本的核心应该也可以用. 但他们至少必须要有以下的功能.

你必须将核心的列功能启动

前面二个是用来使用内存磁盘装置与初始化内存磁盘装置. 第三个是绕回文档系统的支持, 最后二个则是用来挂载 DOS 分割区所必须的支持.

编译核心且不使用模块支持是最简单的选择. 但如果你希望使用模块化支持应该也是可以, 虽然我没有试过. 如果你使用模块化支持, 你必须确定上列的选项是直接编译在核心内而不是编译成模块.

依据核心版本的不同, 你可能需要使用一些修补. 下面是一些简单的修补用来让核心可以将绕回装置作为根目录文档系统使用.

对于 2.0.x 版的核心, 必须将 "loop", 0x0700 这一行加到 /init/main.c 的原始码中而成为下面的样子.

static void parse_root_dev(char * line)
{
        int base = 0;
        static struct dev_name_struct {
                const char *name;
                const int num;
        } devices[] = {
                { "nfs",     0x00ff },
                { "loop",    0x0700 },
                { "hda",     0x0300 },

...

                { "sonycd",  0x1800 },
                { NULL, 0 }
        };

...

}

对于 2.2.x 版的核心, 必须将 "loop", 0x0700 与前后各一行(共三行)加到 /init/main.c 的原始码中而成为下面的样子

static struct dev_name_struct {
        const char *name;
        const int num;
} root_dev_names[] __initdata = {
#ifdef CONFIG_ROOT_NFS
        { "nfs",     0x00ff },
#endif
#ifdef CONFIG_BLK_DEV_LOOP
        { "loop",    0x0700 },
#endif
#ifdef CONFIG_BLK_DEV_IDE
        { "hda",     0x0300 },

...

        { "ddv", DDV_MAJOR << 8},
#endif
        { NULL, 0 }
};

当核心组态设好后, 他必须被编译成 zImage 档 (make zImage). 编译好的文档会被放在 arch/i386/boot/zImage.

3.3 建立初始化内存磁盘装置

建立初始化内存磁盘最简单的方式是将它当成绕回装置挂载. 你必须使用 root 的权限来做这件事. 建立程序如下所示, 这些指令是在 root 的家目录 (/root) 中执行的.

mkdir /root/initrd
dd if=/dev/zero of=initrd.img bs=1k count=1024
mke2fs -i 1024 -b 1024 -m 5 -F -v initrd.img
mount initrd.img /root/initrd -t ext2 -o loop
cd initrd
[建立必须的文档]
cd ..
umount /root/initrd
gzip -c -9 initrd.img > initrdgz.img

这些指令的作用如下所述.

  1. 建立一个给初始化内存使用的挂载点 (一个空目录).
  2. 建立一个指定大小的空文档, 此处我建立一个 1024kB 的文档, 你必须依据你所要放置文档的量来决定这个文档的大小. (文档大小是最后一个参数)
  3. 将这个文档格式化成 ext2 文档系统.
  4. 将这个文档以绕回的方式挂载倒挂载点上.
  5. 切换目录到绕回设备的挂载点中.
  6. 建立必须的文档 (细节将在后面讨论).
  7. 离开绕回文档所挂载的目录.
  8. 将绕回设备卸载.
  9. 建立一个压缩的版本以供后续使用.

初始化内存磁盘的内容

你必须至少有下列的文档放置于初始化内存磁盘中, 否则将不能使用任何指令.

下面是我所用的起始化内存磁盘之内容, 所需空间约 800 kB.

total 18
drwxr-xr-x   2 root     root         1024 Jun  2 13:57 bin
drwxr-xr-x   2 root     root         1024 Jun  2 13:47 dev
drwxr-xr-x   2 root     root         1024 May 20 07:43 etc
drwxr-xr-x   2 root     root         1024 May 27 07:57 lib
-rwxr-xr-x   1 root     root          964 Jun  3 08:47 linuxrc
drwxr-xr-x   2 root     root        12288 May 27 08:08 lost+found
drwxr-xr-x   2 root     root         1024 Jun  2 14:16 mnt

./bin:
total 168
-rwxr-xr-x   1 root     root        60880 May 27 07:56 ash
-rwxr-xr-x   1 root     root         5484 May 27 07:56 losetup
-rwsr-xr-x   1 root     root        28216 May 27 07:56 mount
lrwxrwxrwx   1 root     root            3 May 27 08:08 sh -> ash

./dev:
total 0
brw-r--r--   1 root     root       3,   0 May 20 07:43 hda
brw-r--r--   1 root     root       3,   1 May 20 07:43 hda1
brw-r--r--   1 root     root       3,   2 Jun  2 13:46 hda2
brw-r--r--   1 root     root       3,   3 Jun  2 13:46 hda3
brw-r--r--   1 root     root       7,   0 May 20 07:43 loop0
brw-r--r--   1 root     root       7,   1 Jun  2 13:47 loop1
crw-r--r--   1 root     root       1,   3 May 20 07:42 null
crw-r--r--   1 root     root       5,   0 May 20 07:43 tty
crw-r--r--   1 root     root       4,   1 May 20 07:43 tty1
crw-r--r--   1 root     root       1,   5 May 20 07:42 zero

./etc:
total 3
-rw-r--r--   1 root     root         2539 May 20 07:43 ld.so.cache

./lib:
total 649
lrwxrwxrwx   1 root     root           18 May 27 08:08 ld-linux.so.1 -> ld-linux.so.1.7.14
-rwxr-xr-x   1 root     root        21367 May 20 07:44 ld-linux.so.1.7.14
lrwxrwxrwx   1 root     root           14 May 27 08:08 libc.so.5 -> libc.so.5.3.12
-rwxr-xr-x   1 root     root       583795 May 20 07:44 libc.so.5.3.12

./lost+found:
total 0

./mnt:
total 0

比较复杂的步骤是建立 dev 目录下面的装置控制档. 你可以用 /dev 下面现有的装置控制档为范本, 并以 mknod 程序来建立他们.

/linuxrc 指令档

起始化记忆磁盘中的 /linuxrc 指令稿是用来完成挂载绕回装置所需的前置准备.

下面的范例是以 /dev/hda1 为 DOS 分割区, 并在成功挂载 DOS 分割区后, 将/linux/linuxdsk.img 设定为 /dev/loop0 ;并将 /linux/linuxswp.img 设定为 /dev/loop1.

#!/bin/sh

echo INITRD: Trying to mount /dev/hda1 as msdos

if /bin/mount -n -t msdos /dev/hda1 /mnt; then

   echo INITRD: Mounted OK
   /bin/losetup /dev/loop0 /mnt/linux/linuxdsk.img
   /bin/losetup /dev/loop1 /mnt/linux/linuxswp.img
   exit 0

else

   echo INITRD: Mount failed
   exit 1

fi

前面的 /dev/loop0 装置将被挂载为根目录, 后面的 /dev/loop1 则将被作为内存置换区使用.

如果你希望 root 以外的使用者也能写入 DOS 分颗区, 你必须改成使用 mount -n -t msdos /dev/hda1 /mnt -o uid=0,gid=0,umask=000,quiet. 这会将所有对 DOS 分割区的存取对应成 root, 并且适当的设定权限.

3.4 建立根目录装置

你所使用的根目录装置将是 linuxdsk.img 这个文档. 你可以用与建立起始内存磁盘相同的方法建立这个文档, 所不同处仅在于必须较大, 足以容纳你要安装的程序.

最简单的办法是将现有的 Linux 系统复制到这个文档系统中. 当然你也可以重新安装一套新的 Linux 系统.

假设你已经做过这些事, 你只要作一些小改变.

/etc/fstab 文档必须将根目录磁盘与置换区对应到你在启示内存磁盘中的绕回设备.

/dev/loop0     /      ext2   defaults 1 1
/dev/loop1     swap   swap   defaults 1 1

这将确保核心会使用正确的根目录装置. 也可以用相同的方法加入置换磁盘. 你也必须移除其他根目录磁盘与置换区的对应.

如果你希望在 Linux 启动后能够读取 DOS 分割区, 你必须作下面这些额外的小修改.

建立叫做 /initrd 的目录, 这是再绕回根目录系统挂载后, 初始内存磁盘挂载的地方.

建立一个符号连接 /DOS 指向 /initrd/mnt, 也就是 DOS 分割区被挂载的地方.

在 rc 档中加入类似 mount -f -t msdos /dev/hda1 /initrd/mnt 的指令, 以建立一个 "假的" 挂载, 如此例如 df 等程序才会知道这个挂载. 如果你在 /linuxrc 中用不同的设定, 请自行修正以符合设定.

由于核心在之前便会被载入, 所以你不需要在根目录装置中放置系统核心. 但如果你使用了核心的模块, 你仍然必须将这些模块放在根目录装置中.

3.5 建立置换装置

你所使用的置换装置将是 linuxswap.img. 这个置换装置相当容易建立. 首先如同之前的做法建立一个空文档, 然后执行 mkswap linuxswap.img 来格式化这个置换档.

置换空间的大小依据个人的使用而不同, 但我建议将它设为大于 8MB, 但小于实体内存量.

3.6 建立 MSDOS 目录

你所要使用的文档必须被搬移到 DOS 分割区中.

必须被放在 C:\LINUX 目录下的文档包括

3.7 建立开机软盘

开机软盘的制作与标准 DOS 开机软盘相同.

在 DOS 下使用 format a: /s 以建立开机软盘.

在这张软盘上, 你必须建立一个 AUTOEXEC.BAT 档, 如下所示. 并且复制 Linux 系统核心与压缩过的起始内存磁盘文档, 以及 LOADLIN 执行档.

AUTOEXEC.BAT 仅需要下面这行.

\loadlin \zImage initrd=\initrdgz.img root=/dev/loop0 ro

这会指定要用的系统核心与起始化内存磁盘档以及根目录磁盘的位置, 并将根目录以唯读的方式挂载.


Next Previous Contents