下面将介绍如何建立绕回设备
要建立一个绕回根目录设备必须要有下列事项.
最重要的是必须能存取一个安装好可运作的 Linux 系统. 这是因为绕回设备只能在 Linux 下建立. 也就是说你不可能从无中生有. 而且你必须要能在这个系统上编译核心.
当绕回设备建立之后, 这将是一个很大的文档. 我使用了一个 80 MB 的文档, 如此我才能建立一个 X 终端机; 但如果你希望能做更多事, 这可能也不够. 这个文档必须被复制到 DOS 分割区中, 所以网路或是一堆软盘是必须的.
你所需要的软件包括:
LOADLIN
1.6版以上mount
程序对现在的 Linux 而言, 应该都能符合以上需求.
我是用 2.0.31 版的核心来使用绕回装置, 其他版本的核心应该也可以用. 但他们至少必须要有以下的功能.
你必须将核心的列功能启动
CONFIG_BLK_DEV_RAM
).CONFIG_BLK_DEV_INITRD
).CONFIG_BLK_DEV_LOOP
).CONFIG_FAT_FS
).CONFIG_MSDOS_FS
).前面二个是用来使用内存磁盘装置与初始化内存磁盘装置. 第三个是绕回文档系统的支持, 最后二个则是用来挂载 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
.
建立初始化内存磁盘最简单的方式是将它当成绕回装置挂载.
你必须使用 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
这些指令的作用如下所述.
初始化内存磁盘的内容
你必须至少有下列的文档放置于初始化内存磁盘中, 否则将不能使用任何指令.
/linuxrc
挂载 DOS 文档系统的指令稿. (如下所示)/lib/*
程序所需要的动态连结器与函式库./etc/*
动态连结所需的快取, 虽然静态连结程序不需要, 但可以避免警告信息./bin/*
使用者命令解译器 (此处我使用 ash
, 因为它比 bash
小).
而 mount
与 losetup
程序是用于挂载 DOS 磁盘与设定绕回装置./dev/*
必须的装置控制档, 你至少需要 /dev/zero
以供 ld-linux.so
使用, /dev/hda*
以挂载 DOS 磁盘, 以及 /dev/loop*
以挂载绕回装置./mnt
一个空的挂载点, 以供 DOS 磁盘挂载.下面是我所用的起始化内存磁盘之内容, 所需空间约 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, 并且适当的设定权限.
你所使用的根目录装置将是 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
中用不同的设定, 请自行修正以符合设定.
由于核心在之前便会被载入, 所以你不需要在根目录装置中放置系统核心. 但如果你使用了核心的模块, 你仍然必须将这些模块放在根目录装置中.
你所使用的置换装置将是 linuxswap.img
.
这个置换装置相当容易建立.
首先如同之前的做法建立一个空文档, 然后执行 mkswap linuxswap.img
来格式化这个置换档.
置换空间的大小依据个人的使用而不同, 但我建议将它设为大于 8MB, 但小于实体内存量.
你所要使用的文档必须被搬移到 DOS 分割区中.
必须被放在 C:\LINUX
目录下的文档包括
LINUXDSK.IMG
作为根目录装置的影像档.LINUXSWP.IMG
置换装置.
开机软盘的制作与标准 DOS 开机软盘相同.
在 DOS 下使用 format a: /s
以建立开机软盘.
在这张软盘上, 你必须建立一个 AUTOEXEC.BAT
档, 如下所示.
并且复制 Linux 系统核心与压缩过的起始内存磁盘文档, 以及 LOADLIN
执行档.
AUTOEXEC.BAT
- DOS 下的开机自动执行批次档.LOADLIN.EXE
- LOADLIN
执行档.ZIMAGE
- Linux 系统核心.INITRDGZ.IMG
- 压缩过的起始内存磁盘档.AUTOEXEC.BAT
仅需要下面这行.
\loadlin \zImage initrd=\initrdgz.img root=/dev/loop0 ro
这会指定要用的系统核心与起始化内存磁盘档以及根目录磁盘的位置, 并将根目录以唯读的方式挂载.