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