一、引导程序概述 任何一个操作系统在任何一个硬件平台上的运行都需要一个引导的过程,即,初始化软件环境、把内核从存储介质放到内存当中去,并开始运行。当然对于某些简单软硬件系统,这个过程可能及其简单,而对于 PC 就要略微复杂一些了。 PC 的引导程序上承 BIOS,下接内核的初始化代码,虽然开一次机只运行一次后就不留痕迹了,不过还是相当重要的。 所有的引导程序都在做类似的事情:
历史上,用于 Linux 的最xx的引导程序莫过于 LILO 和 Grub了,作为通用的引导程序,二者用途广泛,但对于一些特殊的场合,譬如引导程序可利用的空间比较有限的可移动存储介质 (通俗地说,包括光盘、软盘、u盘等),它们有些过于厚重了,这就引出了我们今天的主角 ---SYSLINUX/ISOLINUX,现在,你只要知道他们是引导程序就足够了,接下来,我们还要插入一些废话。 二、Initrd initrd = init ramdisk, 顾名思义,就是在启动时使用的一个内存虚拟磁盘,它是系统广泛的硬件支持性的必需品。 我们知道,Linux 的驱动程序是内核的一部分,它们提供了硬件向上层的抽象接口,Linux 内核的核心子系统 ---虚拟文件系统部分的工作强烈依赖于底层硬件驱动程序的支持,在启动过程当中,当某些必备的驱动程序无法使用的时候,比如 EXT2 文件系统、IDE硬盘适配器等无法工作的时候,系统启动将就此中止,发生所谓的``Kernel Panic'',这也是初学者编译内核最常遇到的困难。 然而,我们当然不能将所有的驱动都编译到内核当中去,因为我们不能无限制地加大内核的尺寸,这对于系统资源,尤其是引导过程中非常有限的可用存储资源是难以承受的我们可以把很多驱动程序编译成模块,随用随加载极少数情况,某些模块是相互冲突的,比如 2.4 内核的某些版本之中,reiserfs 和 ext3 两种驱动不能同时被编译到内核当中。 所以,我们只能在内核中放入必要的驱动程序,其余的不那么需要的部分编译成模块放到 /lib/modules/`uname -r`/ 之中,在需要的时候会被加载。 但是,对于具有通用性的内核,是很难论断出哪几种驱动程序才是真正必须的,究竟是 Intel 的 IDE 磁盘控制器还是 AMD/nVidia的,抑或是 VIA 的,乃至光纤通道SCSI磁盘……是阿,这真是个很困扰人的问题,没有一个驱动可以在占用{jd1}少的空间的前提下应付所有的设备,于是,我们退而求其次,寻求一个中间介质 ---ramdisk。 在内核启动前,引导程序首先在内存之中构建一个 ramdisk,成为一个基本文件系统,然后 Linux 内核以此为自己的根文件系统启动,这样的好处是可以不必理会磁盘驱动的问题,只要能驱动 ramdisk 就可以了。 用 ramdisk 启动之后,在 ramdisk 的启动脚本 (一般叫 /linuxrc) 之中,针对硬件尝试 ramdisk 里面的/lib/modules/`uname -r`/,加载恰当的驱动,这时系统已经具备了切换到硬盘或其他介质上的文件系统的条件了。 机不可失,这时,我们首先加载硬盘或光盘、u 盘等启动介质,然后设该介质为根分区,并运行其 init 进程为 1 进程,之后,在 init脚本中,释放掉 initrd 的空间,这就是借助 initrd 的引导过程。在这个过程之中 引导程序帮我们多做了一件事 --- 构建ramdisk, 把 initrd 放入内存。 三、用 SYSLINUX/ISOLINUX 引导软盘和光盘 上文已经说过了,SYSLINUX/ISOLINUX是专门用来引导可移动介质的轻量级引导程序,因为这样的介质通常不会固定只针对一种硬件,initrd 当然是 SYSLINUX/ISOLINUX必须支持的功能了。这两种引导程序其实是一样的,没有多大区别,只是放在不同的设备的引导区罢了。 3.1 配置 SYSLINUX/ISOLINUX 对于这两种引导程序,都会有一段引导代码,写入引导代码的时候,还同时需要一个配置文件: syslinux.cfg/isolinux.cfg,同样,这两个文件也是一样的,{wy}的区别在于文件名,其各个字段的写法如下: DISPLAY xxx.txt 这指定了一个文件名,会在启动的时候显示的内容,该文件甚至可以包含一个 RLE 编码的图形文件,也就是大家在安装光盘启动时看到的那个;不过这个字段不甚重要,我们就略过了。 DEFAULT linux 指定 label 是 linux 的启动选项为缺省,当然也可以是别的。 LABEL linux kernel vmlinuz append initrd=initrd26.gz ramdisk_size=1000000 vga=791 这就是一个启动描述,前面的 label 大家都认识了,之后分别是指定 kernel 和内核参数,其中重要的参数就是 initrd= 指定initrd 的文件和 ramdisk_size= 指定 initrd的尺寸上限。其余的内核参数还可能有很多,不过这里的参数我们一般都可以抄过来。这样的启动选项描述是可以有若干个的。 PROMPT=1 这是说,向用户提示输入选择,直接回车就是缺省选项了 TIMEOUT=0 没有时间限制,当然也可以指定一定时间之后自动进入缺省选项。 好了,就这么多,如果你会用 LILO 的话,用这个一定得心应手,说实话 grub 也差不了太多。 3.2 安装 SYSLINUX/ISOLINUX 配置文件写完了,现在进入实质阶段,这里,两种引导程序还是略有差别的,首先介绍SYSLINUX: 首先格式化引导介质为 FAT16 格式 (软盘似乎应该是 FAT12),我们的例子里面是 U 盘, mkdosfs -F16 -I /dev/sda 我们是操作整个 U 盘,而不是里面的{wy}分区,这种情况不是很多见,只是手上的 U 盘比较特殊,大部分情况下,我们也可以 mkdosfs -F16 /dev/sda1 然后挂在该 U 盘,放入我们的 syslinux.cfg 以及 kernel 和 initrd.gz,还有其他启动所需要的东东,之后 umount 该 U 盘。 * 执行下面操作之前,必须 umount U 盘!* 然后写引导区: syslinux /dev/sda (或 syslinux /dev/sda1,如果是格式化的 /dev/sda1 的话) 至此就完成了。 对于光盘,同样不复杂,我们用 ISOLINUX: 在准备制作 ISO 的目录里添加一个子目录,比如 boot/isolinux/ ,然后放入 isolinux.cfg 和一个对所有光盘都一样的isolinux 提供的引导介质 isolinux.bin,当然还要放入相应的 kernel, initrd 等等,然后,制作 iso的时候要使用 -b 参数: mkisofs -o output.iso \ -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat \ -no-emul-boot -boot-load-size 4 -boot-info-table \ for-iso-dir/ {zh1}的参数就是指定的光盘的目录了,-c 参数的那个文件是自动生成的,不用太担心,其余参数都是固定的。事实上,也常常有人用 isolinux/而不是 boot/isolinux/ ,这都是约定俗成的,你xx可以用自己的。这里的路径都是相对于光盘的根的,而和制作光盘时的工作目录没有关系。 至此,你也会用 SYSLINUX/ISOLINUX 了。 四、实战—— damn small linux + debian installer, 2 in 1 usb disk 1 下载 di 的 hd-image 里的 kernel image 和 initrd,放入 U 盘,同时把 businesscard iso 也放进去,从 iso 里找到 isolinux.cfg,记下里面的启设置。 2 下载 dsl,把 KNOPPIX 目录搬到我们的 U 盘里,把 boot/isolinux/ 里面的 kernel image 和initrd 也放入 U 盘的根目录,这时,U 盘根目录里同时有二者的启动文件了,也记住 dsl 里面的 isolinux.cfg的启动选项。 3 以其中一个的 isolinux.cfg 为基础,加入另一个的启动参数,注意 label 命名不要冲突了就可以了。 4 umount U盘,然后对 U 盘运行 syslinux,写引导区,大功告成。 如前面帖子说过,dsl 的 initrd 之中,只搜索 /dev/sda[1-9] 而不搜索/dev/sda,所以,如果如果像我们一样被迫用 /dev/sda 的话,就不得不修改一下 dsl 的 initrd 里面的 linuxrc 了,除此之外,没有什么其它值得大书特书的了。 LABEL label 而 SYSLINUX 语法: 代码: 注意,"kernel" 并不一定是 Linux 内核,可以是引导扇区或 COMBOOT 文件。 3.32 版后,SYSLINUX 的 label 名不再限制为 DOS 格式。 代码:
使用这些关键字之一而不是 KERNEL 强制文件类型,与文件名无关。 CONFIG 表示使用另外一个配置文件重启引导器。 APPEND - 不附加任何命令,在一个 LABEL 节内可以用来覆盖全局 APPEND。 LOCALBOOT type [ISOLINUX, PXELINUX] IMPLICIT flag_val 如果 flag_val 为 0,除非在 LABEL 声明中明确指定,不会装载内核。 默认值是 1。 ALLOWOPTIONS flag_val 如果 flag_val 为 0,在内核命令行中用户不能指定任何参数,只有 APPEND 声明中指定的选项能够识别。 默认是 1。 TIMEOUT timeout 引导前在 boot: 提示符等待的时间,单位是 1/10 s。用户的键盘输入将取消计时。 默认值是 0,无限等待。 TOTALTIMEOUT timeout 不会被用户的输入取消,用于处理串口故障或类似 "用户离开" 的状况。 默认值是 0。 # 等待 5 s 除非用户输入,但 15 m 后一定启动 TIMEOUT 50 TOTALTIMEOUT 9000 ONTIMEOUT kernel options... timeout 后调用的命令。一般与 DEFAULT 调用相同。如果指定,DEFAULT 只用于用户按 <Enter> 启动时。 ONERROR kernel options... 如果一个内核映像没有找到 (不存在或设置了 IMPLICIT),运行指定的命令。 如果 ONERROR 指令是: 代码: 用户输入的命令行: 代码: SYSLINUX 将执行: 代码: SERIAL port baudrate] flowcontrol] 打开一个串口作为控制台。 CONSOLE flag_val flag_val 为 0,禁止输出到普通视频终端。 flag_val 为 1,允许输出到视频终端 (默认值)。 FONT filename 在显示任何输出之前,装载 .psf 格式的字体 (除了版权行)。SYSLINUX 只装载字体到显卡。忽略 .psf 文件包含的 Unicode 表。只在 EGA 和 VGA 卡工作。 KBDMAP keymap 装载一个简单的键盘映射。 DISPLAY filename 启动时显示 filename 文件内容 (在 boot: 提示符之前)。参见下面的 DISPLAY files。 SAY message 在屏幕上打印 message 消息。 PROMPT flag_val 如果 flag_val 为 0,只在按下了 Shift 或 Alt 键,或 Caps Lock 或 Scroll lock 打开时显示 boot: 提示符 (默认值)。 如果为 1,总是显示 boot: 提示符。 NOESCAPE flag_val 如果 flag_val 为 1,忽略 Shift/Alt/Caps Lock/Scroll Lock。结合 PROMPT 0,强制替换默认引导。 Fn 代码: 在 boot: 提示符下按功能键显示相应文件。可用于实现引导前在线帮助。见下文 DISPLAY files。 使用串行控制台时,按 <Ctrl-F><digit>。如 <Ctrl-F><2> =>F2;<Ctrl-F><A>, <Ctrl-F>B, <Ctrl-F>C 分别为F10-F12。为与早期版本兼容,F10 也可以被输入为 <Ctrl-F>0。 空行将被忽略。 显示文件格式 DISPLAY 和 功能键帮助文件是文本文件。以下代码会被解释: <FF> 代码: 清屏,重置光标。注意屏幕被当前显示色填充。 <SI><bg><fg> 代码: 设置显示的背景和前景色。 代码:
选择亮色 (8-f) 为背景色,导致前景中相应的暗色 (0-7) 闪烁。 在串行控制台颜色不可见。 <CAN>filename<newline> 代码: 如果当前是 VGA 显示,进入图形模式并显示指定的图形文件。文件是 ad hoc 格式,称为 LSS16。所包含的 Perl 程序 "ppmtolss16" 可用于生成这样的文件。 此文件显示为 640x480 16 色模式。一旦进入图形模式,显示特性 (由 <SI> 指定) 略有不同:背景色被忽略,前景色是图像文件中指定的 16 种颜色。因此,ppmtolss16 允许你指定颜色索引。 特别地,颜色索引 0 和 7 应该注意选择:0 是背景色,7 是 SYSLINUX 自身打印文字的颜色。 <EM> 代码: 如果当前是图形模式,返回文本模式。 <DLE>..<ETB> 代码: 这些代码可用于选择那种模式会打印到消息文件的某个部分。任一控制字符选择特定的实际输出模式 (文本屏幕、图形屏幕、串口)。 例如: <DC1>Text mode<DC2>Graphics mode<DC4>Serial port<ETB> 将以控制台输入模式输出。 <SUB> 代码: 文件终止 (DOS) 惯例。 <BEL> 代码: 响铃。 命令行按键 命令行支持以下按键: 代码:
|