启动 |
1。开机自检
在刚开机时,根据X386CUP的特性,代码段(CS,CODE SEGMENT)寄存器的值为全1,指令计数器(IP,INSTRUCTION POINTER)的值为全0,既CS=FFFF、IP=0000。这时CPU根据CS和IP 的值执行FFFF0H处的指令。由于FFFF0H已经到了基本内存的高地址顶端,所以,FFFF0H处的指令一般总是一个JMP指令,以便CPU能够跳到比较低的地址去执行那里的代码,这个地址通常是ROM BIOS 的入口地址。接着,ROM BIOS 进行开机自检,如检查内存,键盘等。在自检过程中,ROM BIOS会在上位内存(UMB,UPPERMEMORY BLOCK)中进行扫描,侃侃是否存在合法的设备控制卡ROM BIOS(如:SCSI卡上的ROM),如果有,就执行其中的一些初始化代码。最后,ROM BIOS 读取磁盘上的第一个扇区并将这个扇区的内存装入内存。
2。预引导
假定硬盘是系统的启动磁盘。硬盘的第一扇区称为主引导记录(MBR, MASTER BOOTRECORD)。MBR 的长度为512字节。可分为两部分:第一部分为引导(PRE-BOOT)区,占了446个字节;第二部分为分区表(PARTITION PABLE),共有66个字节,记录硬盘的分区信息。预引导区的作用之一是找到标记为活动(ACTIVE)的分区,并将活动分区的引导区读入内存。
如果用软盘启动计算机,ROM BIOS 读入的是软盘的引导区,既软盘的第一个扇区。
3。核心映像装入
在LINUX系统中,人们通常把LILO(LINUX LOADER)放在MBR或某个分区的超级块(SUPERBLOCK)中。假定LILO在MBR中,读取MBR后,LILO就会被首先执行。此时,屏幕上出现“BOOT:”字样,接下来的工作是装入LINUX核心映像。如果LILO安装在某个分区的超级块中,通常还会有一个管理开机的程序,这个管理开机的程序负责读取LILO,进而进行核心映像的装入工作。
4。核心启动
核心装入完毕后,CPU的控制权就交给了核心启动代码。此时,核心首先进行硬件的检测和设备驱动程序的初始化,然后运行INIT。INIT 是LINUX核心启动的第一个用户进程,其进程号为1,是系统其它用户进程的祖先。
5。系统初始化
INIT进程负责进行一系列系统初始化程序和脚本文件,/ETC/INITTAB中包含了INIT所做的所有工作。
6。等待用户登录
系统初始化完毕后,INIT 切换到多用户模式,并为每一个虚拟控制台和川行终端启动一个GETTY进程。GETTY进程负责接受和检验用户的登录要求。
至此,LINUX系统的启动工作全部完成。不同核心版本的LINUX 的启动过程有一定的差异,不同发行版本的LINUX 的启动也可能稍有不同,但基本过程是类似的。另外,在“BOOT:”后,利用“LINUX SINGLE”命令可以迫使LINUX进入单用户模式,除不要求用户登录和不启动虚拟终端以外,启动过程的其它部分也基本类似。
一. Bootloader
在Alpha/AXP平台上引导Linux通常有两种方法,一种是由MILO及其他类似的引导程序引导,另一种是由Firmware直接引导。MILO功能与i386平台的LILO相近,但内置有基本的磁盘驱动程序(如IDE、SCSI等),以及常见的文件系统驱动程序(如ext2,iso9660等), firmware有ARC、SRM两种形式,ARC具有类BIOS界面,甚至还有多重引导的设置;而SRM则具有功能强大的命令行界面,用户可以在控制台上使用boot等命令引导系统。ARC有分区(Partition)的概念,因此可以访问到分区的首扇区;而SRM只能将控制转给磁盘的首扇区。两种firmware都可以通过引导MILO来引导Linux,也可以直接引导Linux的引导代码。
“arch/alpha/boot”下就是制作Linux Bootloader的文件。“head.S”文件提供了对 OSF PAL/1的调用入口,它将被编译后置于引导扇区(ARC的分区首扇区或SRM的磁盘0扇区),得到控制后初始化一些数据结构,再将控制转给“main.c”中的start_kernel(), start_kernel()向控制台输出一些提示,调用pal_init()初始化PAL代码,调用openboot() 打开引导设备(通过读取Firmware环境),调用load()将核心代码加载到START_ADDR(见 “include/asm-alpha/system.h”),再将Firmware中的核心引导参数加载到ZERO_PAGE(0) 中,最后调用runkernel()将控制转给0x100000的kernel,bootloader部分结束。
“arch/alpha/boot/bootp.c”以“main.c”为基础,可代替“main.c”与“head.S” 生成用于BOOTP协议网络引导的Bootloader。
Bootloader中使用的所有“srm_”函数在“arch/alpha/lib/”中定义。
以上这种Boot方式是一种最简单的方式,即不需其他工具就能引导Kernel,前提是按照 Makefile的指导,生成bootimage文件,内含以上提到的bootloader以及vmlinux,然后将 bootimage写入自磁盘引导扇区始的位置中。
当采用MILO这样的引导程序来引导Linux时,不需要上面所说的Bootloader,而只需要 vmlinux或vmlinux.gz,引导程序会主动解压加载内核到0x1000(小内核)或0x100000(大内核),并直接进入内核引导部分,即本文的第二节。
对于I386平台
i386系统中一般都有BIOS做最初的引导工作,那就是将四个主分区表中的第一个可引导分区的第一个扇区加载到实模式地址0x7c00上,然后将控制转交给它。
在“arch/i386/boot”目录下,bootsect.S是生成引导扇区的汇编源码,它首先将自己拷贝到0x90000上,然后将紧接其后的setup部分(第二扇区)拷贝到0x90200,将真正的内核代码拷贝到0x100000。以上这些拷贝动作都是以bootsect.S、setup.S以及vmlinux在磁盘上连续存放为前提的,也就是说,我们的bzImage文件或者zImage文件是按照bootsect,setup, vmlinux这样的顺序组织,并存放于始于引导分区的首扇区的连续磁盘扇区之中。
bootsect.S完成加载动作后,就直接跳转到0x90200,这里正是setup.S的程序入口。 setup.S的主要功能就是将系统参数(包括内存、磁盘等,由BIOS返回)拷贝到 0x90000-0x901FF内存中,这个地方正是bootsect.S存放的地方,这时它将被系统参数覆盖。以后这些参数将由保护模式下的代码来读取。
除此之外,setup.S还将video.S中的代码包含进来,检测和设置显示器和显示模式。最后,setup.S将系统转换到保护模式,并跳转到0x100000(对于bzImage格式的大内核是 0x100000,对于zImage格式的是0x1000)的内核引导代码,Bootloader过程结束。
对于2.4.x版内核
没有什么变化。
二.Kernel引导入口
在arch/alpha/vmlinux.lds的链接脚本控制下,链接程序将vmlinux的入口置于 "arch/alpha/kernel/head.S"中的__start上,因此当Bootloader跳转到0x100000时, __start处的代码开始执行。__start的代码很简单,只需要设置一下全局变量,然后就跳转到start_kernel去了。start_kernel()是"init/main.c"中的asmlinkage函数,至此,启动过程转入体系结构无关的通用C代码中。
对于I386平台
在i386体系结构中,因为i386本身的问题,在"arch/alpha/kernel/head.S"中需要更多的设置,但最终也是通过call SYMBOL_NAME(start_kernel)转到start_kernel()这个体系结构无关的函数中去执行了。
所不同的是,在i386系统中,当内核以bzImage的形式压缩,即大内核方式(__BIG_KERNEL__)压缩时就需要预先处理bootsect.S和setup.S,按照大核模式使用$(CPP) 处理生成bbootsect.S和bsetup.S,然后再编译生成相应的.o文件,并使用 "arch/i386/boot/compressed/build.c"生成的build工具,将实际的内核(未压缩的,含 kernel中的head.S代码)与"arch/i386/boot/compressed"下的head.S和misc.c合成到一起,其中的head.S代替了"arch/i386/kernel/head.S"的位置,由Bootloader引导执行(startup_32入口),然后它调用misc.c中定义的decompress_kernel()函数,使用 "lib/inflate.c"中定义的gunzip()将内核解压到0x100000,再转到其上执行 "arch/i386/kernel/head.S"中的startup_32代码。
对于2.4.x版内核
没有变化。
三.核心数据结构初始化--内核引导第一部分
start_kernel()中调用了一系列初始化函数,以完成kernel本身的设置。这些动作有的是公共的,有的则是需要配置的才会执行的。
在start_kernel()函数中,
·输出Linux版本信息(printk(linux_banner))
·设置与体系结构相关的环境(setup_arch())
·页表结构初始化(paging_init())
·使用"arch/alpha/kernel/entry.S"中的入口点设置系统自陷入口(trap_init())
·使用alpha_mv结构和entry.S入口初始化系统IRQ(init_IRQ())
·核心进程调度器初始化(包括初始化几个缺省的Bottom-half,sched_init())
·时间、定时器初始化(包括读取CMOS时钟、估测主频、初始化定时器中断等,time_init())
·提取并分析核心启动参数(从环境变量中读取参数,设置相应标志位等待处理,(parse_options())
·控制台初始化(为输出信息而先于PCI初始化,console_init())
·剖析器数据结构初始化(prof_buffer和prof_len变量)
·核心Cache初始化(描述Cache信息的Cache,kmem_cache_init())
·延迟校准(获得时钟jiffies与CPU主频ticks的延迟,calibrate_delay())
·内存初始化(设置内存上下界和页表项初始值,mem_init())
·创建和设置内部及通用cache("slab_cache",kmem_cache_sizes_init())
·创建uid taskcount SLAB cache("uid_cache",uidcache_init())
·创建文件cache("files_cache",filescache_init())
·创建目录cache("dentry_cache",dcache_init())
·创建与虚存相关的cache("vm_area_struct","mm_struct",vma_init())
·块设备读写缓冲区初始化(同时创建"buffer_head"cache用户加速访问,buffer_init())
·创建页cache(内存页hash表初始化,page_cache_init())
·创建信号队列cache("signal_queue",signals_init())
·初始化内存inode表(inode_init())
·创建内存文件描述符表("filp_cache",file_table_init())
·检查体系结构漏洞(对于alpha,此函数为空,check_bugs())
·SMP机器其余CPU(除当前引导CPU)初始化(对于没有配置SMP的内核,此函数为空,smp_init())
·启动init过程(创建第一个核心线程,调用init()函数,原执行序列调用cpu_idle() 等待调度,init())
至此start_kernel()结束,基本的核心环境已经建立起来了。
对于I386平台
i386平台上的内核启动过程与此基本相同,所不同的主要是实现方式。
对于2.4.x版内核
2.4.x中变化比较大,但基本过程没变,变动的是各个数据结构的具体实现,比如Cache。
四.外设初始化--内核引导第二部分
init()函数作为核心线程,首先锁定内核(仅对SMP机器有效),然后调用 do_basic_setup()完成外设及其驱动程序的加载和初始化。过程如下:
·总线初始化(比如pci_init())
·网络初始化(初始化网络数据结构,包括sk_init()、skb_init()和proto_init()三部分,在proto_init()中,将调用protocols结构中包含的所有协议的初始化过程,sock_init())
·创建bdflush核心线程(bdflush()过程常驻核心空间,由核心唤醒来清理被写过的内存缓冲区,当bdflush()由kernel_thread()启动后,它将自己命名为kflushd)
·创建kupdate核心线程(kupdate()过程常驻核心空间,由核心按时调度执行,将内存缓冲区中的信息更新到磁盘中,更新的内容包括超级块和inode表)
·设置并启动核心调页线程kswapd(为了防止kswapd启动时将版本信息输出到其他信息中间,核心线调用kswapd_setup()设置kswapd运行所要求的环境,然后再创建 kswapd核心线程)
·创建事件管理核心线程(start_context_thread()函数启动context_thread()过程,并重命名为keventd)
·设备初始化(包括并口parport_init()、字符设备chr_dev_init()、块设备 blk_dev_init()、SCSI设备scsi_dev_init()、网络设备net_dev_init()、磁盘初始化及分区检查等等,device_setup())
·执行文件格式设置(binfmt_setup())
·启动任何使用__initcall标识的函数(方便核心开发者添加启动函数,do_initcalls())
·文件系统初始化(filesystem_setup())
·安装root文件系统(mount_root())
至此do_basic_setup()函数返回init(),在释放启动内存段(free_initmem())并给内核解锁以后,init()打开/dev/console设备,重定向stdin、stdout和stderr到控制台,最后,搜索文件系统中的init程序(或者由init=命令行参数指定的程序),并使用 execve()系统调用加载执行init程序。
init()函数到此结束,内核的引导部分也到此结束了,这个由start_kernel()创建的第一个线程已经成为一个用户模式下的进程了。此时系统中存在着六个运行实体:
·start_kernel()本身所在的执行体,这其实是一个"手工"创建的线程,它在创建了init()线程以后就进入cpu_idle()循环了,它不会在进程(线程)列表中出现
·init线程,由start_kernel()创建,当前处于用户态,加载了init程序
·kflushd核心线程,由init线程创建,在核心态运行bdflush()函数
·kupdate核心线程,由init线程创建,在核心态运行kupdate()函数
·kswapd核心线程,由init线程创建,在核心态运行kswapd()函数
·keventd核心线程,由init线程创建,在核心态运行context_thread()函数
对于I386平台
基本相同。
对于2.4.x版内核
这一部分的启动过程在2.4.x内核中简化了不少,缺省的独立初始化过程只剩下网络(sock_init())和创建事件管理核心线程,而其他所需要的初始化都使用__initcall()宏包含在do_initcalls()函数中启动执行。
五.init进程和inittab引导指令
init进程是系统所有进程的起点,内核在完成核内引导以后,即在本线程(进程)空间内加载init程序,它的进程号是1。
init程序需要读取/etc/inittab文件作为其行为指针,inittab是以行为单位的描述性(非执行性)文本,每一个指令行都具有以下格式:
id:runlevel:action:process其中id为入口标识符,runlevel为运行级别,action为动作代号,process为具体的执行程序。
id一般要求4个字符以内,对于getty或其他login程序项,要求id与tty的编号相同,否则getty程序将不能正常工作。
runlevel是init所处于的运行级别的标识,一般使用0-6以及S或s。0、1、6运行级别被系统保留,0作为shutdown动作,1作为重启至单用户模式,6为重启;S和s意义相同,表示单用户模式,且无需inittab文件,因此也不在inittab中出现,实际上,进入单用户模式时,init直接在控制台(/dev/console)上运行/sbin/sulogin。
在一般的系统实现中,都使用了2、3、4、5几个级别,在Redhat系统中,2表示无NFS支持的多用户模式,3表示完全多用户模式(也是最常用的级别),4保留给用户自定义,5表示XDM图形登录方式。7-9级别也是可以使用的,传统的Unix系统没有定义这几个级别。runlevel可以是并列的多个值,以匹配多个运行级别,对大多数action来说,仅当runlevel与当前运行级别匹配成功才会执行。
initdefault是一个特殊的action值,用于标识缺省的启动级别;当init由核心激活以后,它将读取inittab中的initdefault项,取得其中的runlevel,并作为当前的运行级别。如果没有inittab文件,或者其中没有initdefault项,init将在控制台上请求输入 runlevel。
sysinit、boot、bootwait等action将在系统启动时无条件运行,而忽略其中的runlevel,其余的action(不含initdefault)都与某个runlevel相关。各个action的定义在inittab的man手册中有详细的描述。
在Redhat系统中,一般情况下inittab都会有如下几项:
id:3:initdefault:
#表示当前缺省运行级别为3--完全多任务模式;
si::sysinit:/etc/rc.d/rc.sysinit
#启动时自动执行/etc/rc.d/rc.sysinit脚本
l3:3:wait:/etc/rc.d/rc 3
#当运行级别为3时,以3为参数运行/etc/rc.d/rc脚本,init将等待其返回
0:12345:respawn:/sbin/mingetty tty0
#在1-5各个级别上以tty0为参数执行/sbin/mingetty程序,打开tty0终端用于
#用户登录,如果进程退出则再次运行mingetty程序
x:5:respawn:/usr/bin/X11/xdm -nodaemon
#在5级别上运行xdm程序,提供xdm图形方式登录界面,并在退出时重新执行
六.rc启动脚本
上一节已经提到init进程将启动运行rc脚本,这一节将介绍rc脚本具体的工作。
一般情况下,rc启动脚本都位于/etc/rc.d目录下,rc.sysinit中最常见的动作就是激活交换分区,检查磁盘,加载硬件模块,这些动作无论哪个运行级别都是需要优先执行的。仅当rc.sysinit执行完以后init才会执行其他的boot或bootwait动作。
如果没有其他boot、bootwait动作,在运行级别3下,/etc/rc.d/rc将会得到执行,命令行参数为3,即执行/etc/rc.d/rc3.d/目录下的所有文件。rc3.d下的文件都是指向/etc/rc.d/init.d/目录下各个Shell脚本的符号连接,而这些脚本一般能接受start、stop、restart、status等参数。rc脚本以start参数启动所有以S开头的脚本,在此之前,如果相应的脚本也存在K打头的链接,而且已经处于运行态了(以/var/lock/subsys/下的文件作为标志),则将首先启动K开头的脚本,以stop作为参数停止这些已经启动了的服务,然后再重新运行。显然,这样做的直接目的就是当init改变运行级别时,所有相关的服务都将重启,即使是同一个级别。
rc程序执行完毕后,系统环境已经设置好了,下面就该用户登录系统了。
七.getty和login
在rc返回后,init将得到控制,并启动mingetty(见第五节)。mingetty是getty的简化,不能处理串口操作。getty的功能一般包括:
打开终端线,并设置模式
输出登录界面及提示,接受用户名的输入
以该用户名作为login的参数,加载login程序
缺省的登录提示记录在/etc/issue文件中,但每次启动,一般都会由rc.local脚本根据系统环境重新生成。
注:用于远程登录的提示信息位于/etc/issue.net中。
login程序在getty的同一个进程空间中运行,接受getty传来的用户名参数作为登录的用户名。
如果用户名不是root,且存在/etc/nologin文件,login将输出nologin文件的内容,然后退出。这通常用来系统维护时防止非root用户登录。
只有/etc/securetty中登记了的终端才允许root用户登录,如果不存在这个文件,则root可以在任何终端上登录。/etc/usertty文件用于对用户作出附加访问限制,如果不存在这个文件,则没有其他限制。
当用户登录通过了这些检查后,login将搜索/etc/passwd文件(必要时搜索 /etc/shadow文件)用于匹配密码、设置主目录和加载shell。如果没有指定主目录,将默认为根目录;如果没有指定shell,将默认为/bin/sh。在将控制转交给shell以前, getty将输出/var/log/lastlog中记录的上次登录系统的信息,然后检查用户是否有新邮件(/usr/spool/mail/{username})。在设置好shell的uid、gid,以及TERM,PATH 等环境变量以后,进程加载shell,login的任务也就完成了。
八.bash
运行级别3下的用户login以后,将启动一个用户指定的shell,以下以/bin/bash为例继续我们的启动过程。
bash是Bourne Shell的GNU扩展,除了继承了sh的所有特点以外,还增加了很多特性和功能。由login启动的bash是作为一个登录shell启动的,它继承了getty设置的TERM、PATH等环境变量,其中PATH对于普通用户为"/bin:/usr/bin:/usr/local/bin",对于root 为"/sbin:/bin:/usr/sbin:/usr/bin"。作为登录shell,它将首先寻找/etc/profile 脚本文件,并执行它;然后如果存在~/.bash_profile,则执行它,否则执行 ~/.bash_login,如果该文件也不存在,则执行~/.profile文件。然后bash将作为一个交互式shell执行~/.bashrc文件(如果存在的话),很多系统中,~/.bashrc都将启动 /etc/bashrc作为系统范围内的配置文件。
当显示出命令行提示符的时候,整个启动过程就结束了。此时的系统,运行着内核,运行着几个核心线程,运行着init进程,运行着一批由rc启动脚本激活的守护进程(如 inetd等),运行着一个bash作为用户的命令解释器。
DOS 引导区:
OFFSET
0x000 JMP xx Near jump into the program code
0x003 Disk parameters
0x03E Program code loading the DOS kernel
0x1FE 0xAA55 Magic number for BIOS
可见,引导区的结构相对比较简单。它的长度总是512字节。以上,磁盘参数只对DOS有意义。重要的是引导区从0开始,以BIOS的magic number 结束。
从软盘启动比较简单,因为只有一个引导扇区:第一个扇区。硬盘则困难一些,它被分成很多分区。但是,BIOS根本不管分区信息,它象对待软盘一样对待硬盘,仍读入第一个分区,叫作:master boot record.(MBR).
所以MBR也应该和上面介绍的结构一样:从0开始,以BIOS的magic number 结束
在MBR的最后部分,有分区表。如下图:
OFFSET Length
0x000 0x1BE code loading and starting the boot sector of the active
partitian
0x1BE 0x010 partition1
0x1CE 0x010 partition2
0x1DE 0x010 partition3
0x1EE 0x010 partition4
0x1FE 0x0012 0xAA55 Disk parameters
每个分区信息占16字节,结构如下:
1 BOOT Boot flag: 0=not active ,0x80 active
1 HD Begin:head number
2 SEC CYL Begin:sector and cylinder number of boot sector
1 SYS System Code:0x83 linux , 0x82 linux swap etc.
1 HD End:head number
2 SEC CYL End: sector and cylinder number of boot sector
4 low byte high byte Relative sector number of start sector
4 low byte high byte Number of sectors in the partition
所以硬盘可以有4个分区。这四个分区叫做主分区:primary prititions.假如它们不够用,可以设置所谓的扩展分区。 扩展分区包含至少一个逻辑分区。扩展分区的第一个扇区结构类似MBR,它的分区表的第一表项对应第一个逻辑分区。如果存在第二个逻辑分区,那么分区表的第二个表项就包含了一个指针。这个指针指向第一个逻辑分区后面的一个地址。这个地址包含一个分区表。该分区表的第一表项
对应第二个逻辑分区。这样就组成一个链表,从而扩展分区可以有任意多的逻辑分区。
每一个主分区和扩展区都包含一个引导扇区。系统只能从这几个地方之一启动。BOOT标志决定哪个区被引导。
原来,只有主分区,因此,MS-DOS的fdisk和大多数同类工具只能激活主分区..MBR的代码要作以下的操作:
1:确定活动分区。
2:使用BIOS,将活跃分区的启动扇区读入。
3:跳到启动扇区的0位置。
MBR的空间足够完成这些工作。如上所述,每个分区理论上包含一个引导扇区,而且,存在的第二个硬盘也包含和第一个类似的结构。MBR完全可以容纳一个复杂的引导程序。即所谓的boot manager,动态的决定活动分区。Linux 为我们提供了lilo
2 LILO:the linux loader
LILO引导扇区包括一个分区表的空间,所以,LILO即可以安装在MBR中,也可以安装在某个分区的引导扇区。LILO拥有DOS引导扇区的所有功能,而且,它还可以引导逻辑扇区和第二硬盘分区。LILO还可以和另外的引导者合作(例如:NT loader),这样,用户就可以有很多选择。
(注:以下几个标题,为防止引起歧义,用原文)
2.1 LILO started by MS-DOS MBR
如果系统至少有一个linux主分区,(非交换区,且在第一硬盘上),那么LILO就可以安装在这些分区中的一个。当 LILO对应分区被激活后,引导过程如下:
BIOS 读入 MBR
MBR 读入 活跃主分区:LILO所在的分区。
LILO 引导Linux或另外的操作系统。
要引导其它OS且不用LILO很简单,激活那个分区。Linux分区没有任何变化,非常安全。
2.2 LILO started by a boot manager
假如用户不想删除老的boot manager,或者某个OS LILO不能引导,可以考虑该途径。
1. 2. 假如 boot manager 可以引导第二硬盘分区,linux可以装在第二硬盘上。
3 有些 boot manager 甚至可以引导逻辑分区,那LILO就可以装在逻辑分区上。
当然,也要注意以下情况:
1 某些操作系统直接改写MBR,这会将原来的boot manager破坏。
2 重新分区会破坏扩展分区的引导扇区,这是LILO可能要重装。
当安装新的系统时,是否要重新安装(linux)依靠新的boot manager,要么LILO引导扇区被注销,要么boot manager 为它提供一个引导项。重新分区或分区格式化会将LILO和linux全部删除。
2.3 LILO占据MBR
假如整个linux系统都在第二硬盘上,且第一硬盘没有扩展分区,那么,LILO只有装在MBR上。这样,会将老的MBR冲去,所以,在安装LILO前,要将老的MBR(包括分区表)做一个备份。DOS下有很多工具可以完成这个任务。在linux下,这样备份:
# dd if=/dev/hda of=/backup/MBR bs=512 count=1
写会使用命令:
# dd if=/backup/MBR of=/dev/hda bs=446 count=1
这样,原来的MBR就被写会但不包括分区表。如果分区表也要恢复,那么bs=512.
注意,这样,新的分区表会被破坏!
2.4 LILO 文件
与LILO有关的文件通常放在/boot/下,配置文件lilo.conf在/etc/下。包含实际引导系统信息的映射文件有/sbin/lilo安装。对于任何LILO安装,配置文件应该被定置以适合个人需要。
The configuration file:配置文件
基本上,配置文件是一些变量赋值。每一行包含一个标志变量或一个变量赋值.配置文件被特殊的变量赋值分成几个区,每个区引导一个linux或其它OS.
下面解释常见的行:
boot = device
说明那一个设备或哪一个分区包含引导扇区。假如没有给boot赋值,取当前缺省值。
compact
激活一种模式,在此模式下,LILO一次向BIOS请求读入相邻的几个分区。这极大的缩短了装载时间,特别是从软盘启动。
delay=tenths
以10秒为单位,规定LILO在引导第一个引导配置前应等待用户的时间。若没有定义,则直接引导。
Linear
使LILO生成线性地址,而不使用通常的Sector/Head/Cylinder机制。Linux地址机制可以不依赖磁盘的物理结构。
install = boot sector
使用指定的boot sector写入引导扇区,缺省用/boot/boot.b
disktab=disktab
使用指定的disktab,缺省使用/boot/disktab.disktab保存了硬盘物理结构信息。
map=map file
说明映射文件的路径。
message=file 指
定一个文件,该文件的内容将会在LILO引导是被显示。假如没有说明该文件,那么就只会出现"LILO"。
verbose=level
说明LILO的调试级别。从0(不显示任何信息)到5(所有的状态信息)。
backup = backup file
以前引导扇区内容的备份文件。缺省使用/boot/boot.device number
force-backup=backup file
和backup 相同,当时假如备份文件存在,被覆盖。
prompt
指定要用户通过键盘选择要引导的内核。不会缺省选择。
timeout=tenths
设置一个超时值,在此时间内必须有键盘输入,否则用第一个配置。类似,假如超时,就不能再输入密码。一般情况下,该取缺省值,无穷大。
注:delay 与 timeout的区别(joe 认为),delay 是"LILO"出现后用户必须有输入的最长时间。timeout 是用户在按了任意键后,系统等待选择,用户两次击键的最大间隔时间。
serial=port, bps parity bits
设置串口参数。如果LILO会从该文件获取串口参数的话。如果其中之一无效,那所有三个参数都无效。Port从四个标准串口选择一个:0对应COM1 或者/dev/ttyS0.。支持的波特率范围为:100-9600。所有校验设置都支持(n:none,e:even,o:odd)bits为7或者8。缺省为serial=0,2400n8.
Ignore-table
让LILO忽略被破坏的分区表。
fix-table
允许LILO将每个分区的(sector/head/cylinder)地址转化为线性地址。通常,分区地址从cylinder boudary开始。某些操作系统,会改变这一点。由于LILO只能将它的启动扇区写于两种地址都一致的分区上,不正确的3D地址可以用fix-table来纠正。但是,这种纠正不能被保证是永远的,所以重分区以保证对齐cylinderboudary 是最好的选择。
password=password
为引导配置设置password
restricted
放松对password的限制。只有用户想传附加的启动参数给内核时才需要password
optional
允许配置的几个内核有错误的,或者不存在,如果不说明optional,LILO遇到这种情况就会打印一些错误信息然后退出。
每个从LILO引导的配置从image行开始。
Image = kernel
Label = name
Image包含要引导的内核。Label是给用户选择用的。Image行通常指向一个设备, 例如/dev/fd0,可以找到内核的范围用range来注明。
range = range
range可以用start sector -end sector 或者 start sector + length 表示。例如:
image = /dev/fd0
label = floppy
range = 1+512
以下变量赋值有可能出现:
append=string
将string作为引导参数传给内核。例如,硬件参数。
literal=string
和append查不多。但是,他会冲掉原来的设置。所以不能被全局说明。
ramdisk=size
设置RAM disk的大小。
read-only
read-write
设置根文件系统的访问方式。
root=device
设置根文件系统存在的设备。
vga=mode
屏幕设置。可能模式为:normal,extended 和ask. 。
以下设置是针对别的操作系统的:
loader=loader
说名用来引导操作系统的文件。缺省为 /boot/chain.b . 另外,LILO包含以下的loader:
os2_d.b 可以从第二硬盘上引导os/2
any_d.b 在引导操作系统之前试图将两个硬盘的次序颠倒,从而可以引导第二硬盘上的os.
table=device
说明一个设备,该设备的某个分区上存放要引导的os.假如没有说明table,
LILO就不会将该信息传给要引导的osunsafe
关掉对要引导的os的检查。只有要从软盘引导时,才使用该设置。没有该设置,每次map installer开始运行时,引导盘都要插入软驱。
The disktab file
disktab文件包含LILO要引导的设备的物理结构信息。通常,这些信息可以从设备驱动程序获取。所以,只有这种方法不行时才会用到disktab 文件。在此情况下,如果文件不能用,LILO报告错误信息:
geo_query_dev HDIO_GETGEO(dev …)
或者
HDIO_REQ not supported for your SISI controller
Please use /boot/disktab
然后,物理结构信息就必须手工地输入。
# /boot/distab-LILO parameter table
#
#This table contains the geometry parameters for SCSI and
# IDE disks,which can not be recognized automatically
# Entries in this table overwrite recognized parameters!
#
# Dev. BIOS Secs/ Heads/ Cylin - Par.
# num. Code track cyLin. Ders. Offset
(optional)
#0x800 0x80 32 64 202 0 # /dev/sda
各个域含义如下:
0x800
设备号.由主副设备号组成。
设备号.由主副设备号组成。
0x80
设备的BIOS 码。0x80代码系统的第一个硬盘。0x81第二个,……
所有同一硬盘上的分区该值相同。
32,64,203
sector 数目(每个track)
heads 数目
cylinders 数目
0
分区的开始。也可以从分区表中读,所以可以不说明。
2.5 LILO 启动信息
在启动过程中,LILO会显示'LILO',如果LILO出错退出,可以根据显示来判断系统的出错原因。
没有信息:LILO根本就没有被读入,没安装LILO,或LILO驻留的分区没被激活。
Lnumber : LILO的第一部分被读入并开始执行。但第二部分不能被读入。后面的数字表明出错原因。这可能是由于硬盘的物理错误或不正确的物理结构信息。
LI: LILO的第一部分可以读入第二部分,第二部分执行时出错。这可能是不正确的物理结构信息或重装了boot.b而没有运行LILO重新安装。
LIL:LILO的第二部分启动起来了,但是不能从map文件读入descriptor tables.这说明不正确的物理结构信息或物理错误。
LIL?: LILO的第二部分被读到不正确的地址。原因同LI
LIL-: descriptor tables有错。这可能是不正确的物理结构信息或重装了map file而没有运行LILO重新安装。
=====================================================================
LILO.CONF(5)
名称
lilo.conf-lilo的配置文件。
描述
本文件,缺省位置为etc/lilo.conf,由引导装入程序的安装程序
LILO 读取。
其表现可能如下:
boot=/dev/hda
delay=40
compact
vga=normal
root=/dev/hda1
read-only
image=/zImage-2.5.99
label=try
image=/zImage-1.0.9
label=1.0.9
image=/tamu/vmlinuz
label=tamu
root=/dev/hdba
vga=ask
other=/dev/hda3
label=dos
table=/dev/hda
本配置文件指定 LILO 使用在/dev/hda路径上的主引导记录。(关于使用 LILO 的不同方式以及其与其他操作系统间交互作用,参见 LILO 文档中的USER.TEX)
启动时,引导装入程序会等待 4 秒的时间(40 deciseconds)让你按SHIFT 键。如果未按,则上述提及的第一核心映象(zImage-1.5.99,可能你5分钟之前才装上的)将被启动。如果按下了SHIFT键则引导装入程序就会问你要启动哪一个映象。 万一你忘了该选择启动哪个映象, 按[TAB](或[?]如果你有一个美国标准语键盘的话)就会有个菜单给你选择。你在这时可以选定或者启动这个全新的内核,或者启动一个原来可靠的内核,或一个在其他根文件系统上的内核 (当你在自己常用的根文件系统上做了什么傻事),或者启动一个不同的操作系统。在 LILO.CONF 中提及的映象可多达16 个。
由上可见,一个配置文件以一系列的全局选项开始(如例子中的开始的6 行),随之是不同映象选项的描述。在映象描述中的选项将会覆盖全局选项所设定的内容。
全局选项部分
其有许多可能的关键词。下面的描述几乎是照抄于 USER.TEX(仅有少许缩略)
backup=backup-file
将原引导扇区拷贝到备份文件(其也有可能是一个设备,如/dev/null)而非/boot/boot.NNNN
boot=boot-device
设定包含引导扇区的设备的名称(如一个硬盘的分区)。如果未指定该关键字引导扇区将从当前作为根文件系统安装的设备中读取(或者可能也会写入)。
change-rules
定义引导时对分区类型数的改变('hiding')。详细资料请参看user.tex 中“分区类型改变规则“一节。
compact
试图将相邻扇区的多次读取请求合并成一次读取请求。这样就大幅度地减少了读取时间,并使系统描述(MAP)更小。在从软驱进行读取时尤其要使用 'compact' 选项。
default=name
使用特别指定的映象作为默认的启动映象。如果未设置 'defaul' 选项,则将使用在该配置文件中最早出现的那个映象作为启动映象。
delay=tsecs
指定引导装入程序在启动第一个映象之前应等待的时间为多少个 10 分之一秒。这对于在键盘可用后立即从硬盘上启动系统很有用。如果未设置 'delay' 选项或设为 0,则引导装入程序就不会等待。
disc=device-name
定义特定硬盘的非标准参数。具体细节参见 USER.TEXT 中的硬盘分区结构一章。其对于定义 'BIOS=' 参数尤其有用。若你的硬盘的 BIOS 数据是 0x80 ,0x81(十六进制)等等,将无法判断哪一块 Linux 磁盘与哪一块 BIOS 磁盘相对应(因为这决定于 BIOS 的设置和 BIOS 的类型)。因此若你采用的是非一般的安装,那你就需要说明 LINUX 磁盘和 BIOS磁盘间的对应关系。比如:
desk=/dev/sda
bios=0x80
disk=/dev/hda
bios=0x81
就会说明你的 SCSI 盘是第一个 BIOS 盘,而你的(主硬盘)IDE盘是第二个 BIOS 盘。
disktab=disktab-file
指定磁盘参数表的名称。若未指定“disktab”选项,则磁盘描述(Map)装入程序会寻找 /etc/disktab 文件。并不提倡disktab选项使用。
fix-table
这个选项使得 LILO 可对分区表上的 3D 地址进行调整。 每个分区表入口包含有该分区的最前和最后一个扇区的 3D 地址(扇区/磁头/柱面 以及线性地址。 如果一个分区不是以磁道号定位的, 且某个其他操做系统 (如PC/MS-DOS 或 OS/2 ) 正在使用同一磁盘,他们就有可能导致 3D 地址的改变。仅当分区的两个地址类型相一致时 LILO 才能保存其启动扇区。 如果设定了 'fix-table' 选项,lilo 就可重新调整错误的 3D 地址。
警告:这并不能保证其他的操做系统以后就不会试图重设该地址。也可能这种变化有其他不可预料的副作用。正确的修改方式是用可以轨道定位分区的程序来重新对磁盘驱动器分区。并且,对一些磁盘来说如一些可进行地址转换的大的EIDE磁盘),在某些情况下, 会不可避免的出现分区表入口相冲突的现象。
force-backup=backup-file
与 'backup' 类似,但若有旧的备份文件存在则会将其覆盖。
ignore-table
告知LILO忽略作废的分区表。
install=boot-file
将指定的文件作为新的引导扇区来安装。若未设置 'install' 选项,则将boot/boot.b作为默认缺省值使用。
linear
产生线性扇区地址而非“扇区/磁头/柱面”地址。线性地址不依赖于磁盘的分区结构,且在运行时被翻译。注意如果使了'linear'选项则可能使启动盘不能被移植,这是因为BIOS中用于决定磁盘分区结构的服务对软盘的作用不稳定。在对大硬盘使用'linear'选项时,由于3D扇区地址在启动前是未知的,故 /sbin/lilo 可能会产生对不可访问的磁盘区域的一个参考。
lock
允许自动记录引导命令行,作为以后启动的默认缺省值。这样,在手工取消之前lilo会锁定一个选项。
map=map-file
定位磁盘描述(MAP)文件。若未指定 'map' 选项,就会使用 /boot/map文件。
message=message-file
指定一个含有在运行启动提示符前显示的信息的文件。在显示出 'LILO' 后等待按键的时间里不会有信息显示。在信息中,用FF字符([Ctrl + L])清空本地显示器。信息文件的大小限制在65535字节以内。如果信息文件被改动或取消则必须重建磁盘描述(Map)文件。
nowarn
使关于以后可能危害的警告失效。
optional
使单一映象选项 'optional' (见后)应用于所有映象。
password=password
使单一映象选项 'password=...' (见后)应用于所有映象。
prompt forces
不等待任何的按键事件发生就直接进入启动提示符模式。如设定了 'promp'选项而没设定 'timeout' 选项,则不能自行启动。
restricted
使单一映象选项'restricted'(见后)应用于所有映象。
serial=parameters
允许使用来自串行口的控制。指定的串行口将会被初始化,引导装入程序就会从该串行口及PC键盘接受输入。在串行线上发送暂停(break)指令和按下键盘上的 SHIFT 键的效果是一致的,都会引起引导装入程序的注意。如果串行线比键盘输入更不安全,如该线与 MODEM 相连时,则所有启动映象都应设密码加以保护。参数串的格式如下:
<port>[,<bps>[<parity>[<bits>]]]
<port>:表串行口的数目,最小为0。0对应于COM1并指定为/dev/ttyS0,等等。所有四个端口均可用(如果可以使用的话)。
<bps>:串行口的比特率。 以下比特率可被支持:110,150,300,600,1200,2400,4800及9600bps。默认值是2400bps。
<parity>:表在串行口上使用的奇偶效验。引导装入程序忽略输入的奇偶效验位,并除去第八位。以下字符可用来描述奇偶效验:n表示无相同,e表示偶数的相同,o表示奇数的相同。
<bits>:在一个字符中的位的数目。仅支持7或8位。若奇偶效验是 'none' 则默认是8,若奇偶效验是'even'或'odd',则默认是7。
若设定了'serial'选项,则'delay'的值就自动上升为20。例如:serial=0,2400n8就会用缺省值参数来安装COM1。
timeout=tsecs
为键盘输入设定一个超时选项(以10分之一秒为单位)。若在指定的时间内没有按键则第一个映象就会被自动启动。同样,如过用户停顿过长则密码输入就会被取消。默认的超时值是无限。
verbose=level
用以打开大量的进程报告。数目越大则给出的冗长输出越多。如果在 LILO命令行中附加参数 -v,则冗长标准也相应增加。最大的冗长标准是5。
另外,内核配置参数 append,ramdisk,read-only,read-write,root以及vga都可在全局选项中被设定。如果在相应的核心映象的配置栏中没对其加以指定,该设定值其就会被用做默认的缺省值。
单一映象部分
一个单一映象或者以一行
image=pathname
开始(以提示含有一个LINUX内核的启动映象的文件或设备),或以一行
other=pathname
开始以提示启动其他独立的系统。
在前一例中,如果一个映象行指定是从一个设备启动,则必须用
range=start-end
提示被描述的扇区范围。
在后一例中,有3个选项可供选择。
laoder=chain-loader
该参数指定了将使用的连锁装入程序。使用默认缺省/boot/chain.b。如果是从其他设备而非第一硬盘或软盘启动则必须指定连锁装入程序。
table=device
其指定含有分区表的设备。若未指定该参数,引导装入程序就不会把分区信息传送到已启动的操做系统。(一些操做系统有其他的方式来决定从哪个分区来启动。如,MS-DOS将其的启动盘分区结构或分区保存到引导扇区里)。应注意若一个已定位且引用了 'table' 选项的分区表被修改则必须重新运行/sbin/lilo文件程序。s
unsafe
在创立磁盘描述(Map)时不要访问启动扇区。 这将取消一些正确性检查,包括分区表检查。如果启动扇区是在一个固定格式化的软盘驱动器上,则在运行定位装载程序时使用 unsafe 选项就不需插入可读取的磁盘到驱动器里。
以下选项在这两例中均可运用。
label=name
引导装入程序使用每个映像说明的主文件名(不包含路径)来标识该映像。通过设定变量'label'可使用不同的名称。
alias=name
通过指定一个别名可对同一个目录使用第二名称。
lock(见前)
optional
删去在磁盘描述表创立时不可用的映像。这对于在指明测试并不总是可用的内核很有用。
password=password
用密码保护映像。
restricted
若是在命令行被指定各参数则只在启动映像使需要输入密码。
内核选项部分
如果被启动的映像是一个LINUX内核,则可以将命令行参数传送到该内核。
append=string
将指定的各选项增加到传送于内核的参数行。其典型的运用于指定不能完全自检或彻查对其有危害的硬盘的参数。比如:
append="hd=64,32,202"
literal=string
与 'append' 类似,但会取消所有其他选项(如根驱动器的设定)。由于用'literal' 选项可在无意之间删掉重要的选项,故该选项不能设在全局选项中。
ramdisk=size
该选项指定了任选RAM磁盘的大小。0 表示不应创立任何RAM磁盘。若不指定该参数,则使用在根文件系统中建立的RAM磁盘大小。
read-only
该参数指定根文件系统应该以只读的形式装载。典型的是,该系统的起始程序稍后将以可读写方式重新装载根文件系统。
read-write
其指定根文件系统应以可读写方式装载。
root=root-device
该参数指定应作为根文件系统装载的设备。如果目前使用的是指定的名称,则根驱动器就设在根文件系统目前所在的设备上。如果根设备被 -r 参数所修改,则使用相应的设备。若未指定 'root' 参数,则使用包含核心映象的根设备设置(该设置是编译内核时在内核的 Makefile 文件中用 ROOT_DEV变量设定的,并稍后可用 rdev(8)程序修改)
vga=mode
其指定在启动时应选择的 VGA 文本模式。 下列数值可被识别 (忽略大小写):
normal:选择普通 80x25 文本模式。
extent(或ext):选择 80x50 文本模式。
ask:停止并要求用户的输入(在启动时)
<number>:使用相应的文本模式。在启动时用vga=ask选项或按[Enter]都可获得一个可用模式的列表。
若未指定该参数,则使用在核心映像中获得的 VGA 文本环境。(该设置是编译内核时在内核的 makefile 文件中用 SVGA_MODE 变量设定的,稍后可用 rdev(8)程序修改)
参见
lilo,rdev(8)
lilo的发布版本来源于广泛的文件,以上部分只是这些文件的选录。
通常我们谈到LILO,会涉及到两个方面——LILO引导程序和LILO安装命令/sbin/lilo。为了不至于混淆这两个概念,本文将用LILO表示LILO引导程序,而lilo表示/sbin/lilo。
一般地,LILO使用一个文本文件/etc/lilo.conf作为其配置文件。lilo读取lilo.conf,按照其中的参数将特定的LILO写入系统引导区。任何时候,修改了/etc/lilo.conf,都必须重新运行lilo命令,以保证LILO正常运行。lilo.conf使用的配置参数很多,配置起来也相当复杂。下面以RedHat Linux为例作一些初步探讨,RedHat的lilo程序包版本为0.20,别的Linux发行版本可能会有所出入,但不会太大。
lilo.conf文件中的配置参数分为两部分,一部分是全局参数,另一部分是引导映像参数。与Linux系统其他的配置文件一样,“#”号后的一行文字表示注释。
一、LILO的全局参数
全局参数是全程有效的,它可以出现在文件lilo.conf中的任何地方。以下是具体的参数项:
1.backup=backup-file
在装入LILO之前将原先的引导区备份到backup-file,而不是RedHat 缺省的/boot/boot.NNNN。也可以备份到一个设备上,如: /dev/null。注意:如果原先已有一个同名文件,该参数将被忽略。我们可通过这个备份恢复原先的引导扇区:
dd if=/boot/boot.NNNN of=/dev/hda bs=446 count=1
原先的MBR。(注:虽然boot.NNNN有512字节,但只能恢复前446字节到MBR。)
2.boot=boot-device
指定一个用于安装LILO的设备。通常LILO可安装在如下几个地方:
MBR:第一个硬盘的主引导区, 对应于/dev/hda、/dev/sda等。
Root:Linux根分区的超级块(Super block), 对应于/dev/hda1、/dev/hda2、/dev/hda5、/dev/sda1、/dev/sda5等。
Floppy:LILO安装在软盘上,对应于/dev/fd0。
不指定时,lilo缺省安装在根分区超级块上。
3.compact
该参数用于优化LILO,产生一个更小的“map”文件。如果在软盘上安装LILO,强烈推荐使用此参数。
4.default=name
指定缺省引导的操作系统。如default=dos 表示将label为DOS的系统作为缺省引导的操作系统。如不指定该参数,排在lilo.conf中的第一个操作系统将作为缺省操作系统。
5.delay=tsecs
在没有指定“prompt” 参数时,LILO将立即引导缺省的操作系统,“delay”参数在这之间插入一段延时,单位是1/10秒。
6.disk=device-name
为某些非标准硬盘定义参数。其内部还包括有几个可选的子参数。
bios=〈bios_device_code〉: 设备号。十六进制数0x80表示第一硬盘;0x81表示第二硬盘,依此类推。
sectors=〈sectors〉:硬盘扇区数。
heads=〈heads〉:硬盘磁头数。
cylinders=〈cylinders〉:硬盘柱面数。受系统BIOS限制,柱面数必须在1024以内。
partition=〈partition_device〉:用于物理定位特殊硬盘上的分区,有一个子参数start。
start=〈partition_offset〉:每一分区的起始扇区。
例如:
disk = /dev/sda
bios=0x80
#指定SCSI硬盘为第一硬盘
sectors = 32
heads = 64
cylinders=632
#硬盘参数为632/64/32
partition=/dev/sda1
start=2048
#第一分区起始扇区为2048
partition = /dev/sda2
start=204800
#第二分区起始扇区为204800
partition = /dev/sda3
start = 500000
partition = /dev/sda4
start = 900000
当机器上有两块硬盘,一块为SCSI硬盘,另一块为IDE硬盘时,LILO很有可能无法自动识别它们的主、从顺序,这时可进行如下设置:
disk = /dev/sda
bios = 0x80
disk = /dev/hda
bios = 0x81
#SCSI硬盘为主硬盘,IDE硬盘为从硬盘
该参数是为Linux无法识别的硬盘准备的,一般Linux可以正确识别和使用大多数硬盘,除非最坏的情况,否则不用设置它。
7.force-backup=backup-file
类似“backup”参数,但是将覆盖原有的同名文件。
8.ignore-table
通知lilo忽略无效的硬盘分区表。
9.install=boot-sector
LILO实际上包含有几个部分,而这几部分都存放在/boot/boot.b文件中。如果忽略“install”参数,则lilo认为install=/boot/boot.b。
10.linear
产生用于替换硬盘sector/head/cylinder地址(硬盘几何参数)的linear扇区地址。linear地址在运行时产生并且不依赖于硬盘几何参数。某些SCSI硬盘和一些以LBA方式使用的IDE硬盘可能会需要使用这个参数。注意,在将LILO安装到软盘上时不能使用“linear”参数。
11.lock
出现LILO提示后立即按最近一次的引导映像启动计算机。也就是说,当我们在lilo.conf中加入了该参数,然后运行lilo安装LILO,再重新启动计算机,这时LILO会提示我们选择引导哪一种操作系统,这一选择将被LILO记录下来,即“锁定”,下次启动计算机时,LILO将忽略“delay”、“prompt”等参数及键盘输入而直接跳转到其“锁定”的操作系统。
12.map=map-file
指定map文件。 没有本项时缺省使用/boot/map,每次执行lilo命令都会产生一个新的map文件。
13.message=message-file
该命令用于指定一个包含注释信息的文件,该文件将在系统打印出字符串“LILO”之前显示。如果在LILO启动时想获取较多的信息,可以编辑一个文件,再使用该命令就可以了。文件中如果包含有ASCII码为0xFF的字符(Ctrl+L)则表示清屏。注意,文件的大小不能超过65535个字节。每次文件改变之后,都必须重新运行lilo命令重建map文件,以保证其正常显示。
14.optional
当用于启动的引导映像不存在时,该参数使lilo忽略它。这对用于测试一个不长期存在的Linux核心是有用的。
15.password=password
为LILO设置口令保护,每次重新启动计算机提示用户输入口令。设置了口令后,建议将lilo.conf的文件属性改为600,以免让非root用户看到口令。
16.prompt
给出“boot:”提示,强制LILO等待用户的键盘输入,按下回车键则立即引导默认的操作系统,而按下Tab键则打印可供选择的操作系统。当“prompt”被设置而“timeout”没有被设置时,系统会一直处于等待状态而不引导任何操作系统。不设置该参数时,LILO不给出“boot:”提示而直接引导默认操作系统,除非用户按下了Shift、Ctrl、Alt三键中的任何一个。大多数情况下,如果你的硬盘上有多个操作系统,建议使用参数,它留给用户一个选择的余地。
17.restricted
与“password”联用,使“password”仅作用于在LILO提示后有命令行输入的时候。
18.serial=parameters
使用串行口控制。这将初始化指定的串口,并将使引导管理器能接受来自串口的输入。从串口发送一个中断信号相当于从控制台键盘上按下Shift键,它同样会被LILO捕捉到。如果不能保证来自串口的访问和控制台一样安全,比方说有一个modem连在串口上,建议为每个引导映像加上口令保护(password)。参数串有如下语法:
〈port〉[,〈bps〉[〈parity〉[〈bits〉]]]
〈port〉:数字表示的串口号,0表示COM1,其余类推。所有四个串口都可被使用。
〈bps〉:串口速率,支持110、 150、300、600、1200、2400、4800和 9600 bps,缺省值为2400bps。
〈parity〉:设置串口校验。一般情况下,LILO忽略奇偶校验。n表示无校验,e 表示偶校验,o 表示奇校验。
〈bits〉:字符位数,只能取7或8,缺省值是8。当有奇偶校验时只能取7。
如果设置了“serial”,即使没有设置“delay”,系统也会将“delay”项的值自动增加20。
19.timeout=tsecs
设置等待键盘输入的时长,单位是0.1秒。超过这段时间没有输入则为超时,系统将自动引导缺省的操作系统。如果不设置本参数,缺省的超时时间长度为无穷大。
二、引导映像参数
引导映像参数作用于每一个引导映像区。如果某一引导映像参数(例如:password)与全局参数的定义相抵触,则以该引导映像参数的定义为准,但仅限于该引导映像区。以下是具体参数项:
image=pathname
设置包含Linux核心引导映像的文件或设备。
other=pathname
设置包含非Linux操作系统,如DOS、SCO UNIX、Windows 95等系统引导映像的文件或设备。
range=start-end
如果“image”参数被设置为一个设备,则Linux核心引导映像的存放范围必须被设置。
image = /dev/fd0
range = 1-512
# Linux核心引导映像存放在软盘上的第一至512扇区
label=name
通过此参数来标识当前操作系统,即操作系统名。用户可通过在LILO提示后输入“标识”来决定引导哪一个操作系统。
alias=name
给当前操作系统起一别名。
lock
类似同名全局参数。
optional
类似同名全局参数。
password=password
类似同名全局参数。
restricted
类似同名全局参数。
以下两个参数项用于非Linux操作系统:
loader=chain-loader
如果要引导第二块硬盘上的非Linux操作系统或将LILO安装到软盘,这个参数是必需的。不指定时,缺省值是/boot/chain.b。如启动第二块硬盘上的MS-DOS或Windows 95,可定义loader=/boot/any_d.b;对于OS/2,则为loader=/boot/os2_d.b。
作为一个特殊的功能模块,any_d.b已不合时宜,在0.20版以后的lilo程序包中已不再包含它并将其功能整合进chain.b,os2_d.b亦有所变动。它们的功能可用如下语句代替。
例:
other = /dev/hdb1
loader = /boot/any_d.b
替换为:
other = /dev/hdb1
map-drive = 0x80
to = 0x81
map-drive = 0x81
to = 0x80
对于os2_d.b:
other = /dev/hdb1
loader = /boot/os2_d.b
替换为:
other = /dev/hdb1
loader = /boot/os2_d.b
map-drive = 0x80
to = 0x81
map-drive = 0x81
to = 0x80
map-drive=〈bios_device_code〉
通知chain.b装入重映射软驱或硬驱的内存驻留驱动程序,使用它可以引导不同硬盘上的不同操作系统,条件只有一个, BIOS必须能访问硬盘。“map-drive”后跟有变量“TO=〈盘设备号〉”。实际上,“map-drive”起到了“软”交换两个软驱或硬驱主、从顺序的作用,避免了手工接线的麻烦。
例:交换软驱
map-drive = 0
to = 1
map-drive = 1
to = 0
交换硬驱(参看loader参数例)
table=device
指定包含非Linux系统分区的主设备。举例来说,如果Windows 95在第一个IDE硬盘的第一个基本分区上,即/dev/hda1上,那么必须定义table=/dev/hda 。
三、核心参数
如果LILO引导的是Linux系统,我们可用下面命令传递一些参数给Linux核心。除“literal”之外,它们也可用于全局参数区。
append=string
append传递一个特殊硬件的参数串string给Linux系统的核心。它常用来配置一些Linux不能正确测试到的硬件设备。例如:
append = "hd=64,32,202"
通知Linux核心,硬盘参数为64柱面、32磁头、202扇区。具体的参数串设置可参看/usr/doc/HOWTO/BootPrompt-HOWTO文件。
literal=string
类似于“append”,但它将撤消所有的其它核心参数(比如设置了root设备)。因为“literal”会不分青红皂白地撤消一些必需的、重要的参数,所以不能将它设置在全局参数区。
ramdisk=size
指定RAM盘的大小。size为零时不建立RAM盘。忽略此参数时,RAM盘大小由Linux核心引导映像决定。
read-only
通知LILO以只读方式载入根文件系统。通常我们在检查根文件系统时需要将根文件系统以只读方式载入。Linux系统在每次启动时也会将根文件系统以只读方式载入,待例行的文件系统检查后再将其重新载入为读写方式。
read-write
通知LILO以读写方式载入根文件系统。
root=root-device
指定被安装根文件系统硬盘分区设备。
vga=mode
指定引导Linux系统时的VGA模式。有以下取值:
normal:常规80×25文本模式
extended (or ext): 80×50文本模式
ask: 引导时询问用户使用哪一种VGA模式,这时敲回车键将显示一个可分配的VGA模式表。
如果不指定VGA模式,系统将缺省地使用包含在系统核心里的VGA模式值。
四、lilo.conf配置实例
有了这些基础知识,我们可以很容易地按照自己的意图配置LILO。请看一个lilo.conf文件的例子:
boot=/dev/hda #将LILO安装在MBR。LILO作为主引导管理器
message=/boot/message #注释为/boot/message
compact #产生一个更小的“map”文件
map=/boot/map #指定“map”文件为/boot/map
install=/boot/boot.b
password=zhoudi #设置口令
vga=normal #80x25文本模式
linear #使用“linear”地址
prompt #提示用户键盘输入
timeout=50 #超时时长为5秒
default=dos #缺省引导label为dos的操作系统
#设定Linux
image=/boot/vmlinuz-2.0.34-1
#设置Linux核心引导映像
label=linux #标识为linux
root=/dev/hda1 #设置根文件系统
read-only #LILO以只读方式载入根文件系统
#设定MS-DOS或Windows 95
other=/dev/hda2 #DOS分区为第一个IDE硬盘的第二分区
label=dos #标识为dos
table=/dev/hda #主设备为第一个IDE硬盘
#设定SCO UNIX
注意:SCO分区必须设为活动(active)分区并将LILO安装在MBR上。
other=/dev/hda3
label=sco
table=/dev/hda
这个例子中,LILO是作为主引导管理器来管理机器上所有操作系统的。LILO也可作为二级引导管理器,这只要将“boot”参数改为根分区就可做到。例如:
boot=/dev/hda1
以这种方式使用LILO时,Linux根分区必须用DOS或Linux的fdisk程序将其设置为活动分区,并且这种方式只对硬盘主分区(不是扩展或逻辑分区)有效。
LILO还可以启动第二个以上的操作系统。在我的机器上有两块希捷硬盘,一块硬盘为8.4GB,另一块为1.2GB,都以LBA模式接在主IDE口上。8.4GB跳线为主盘,1.2GB跳线为从盘,Linux核心很容易地就将它们辨认出来并能正常使用,1.2GB的硬盘上安装了MS-DOS 6.22。笔者是这样设置lilo.conf的:
disk=/dev/hda
bios=0x80
#由于IDE硬盘存在双硬盘问题,所以当启动DOS系统时,会提示“无系统盘或系统盘错!”,需修改程序如下。
disk=/dev/hdb
bios=0x81
boot=/dev/hda
map=/boot/map
install=/boot/boot.b
linear
prompt
timeout=50
default=dos
image=/boot/vmlinuz-2.2.11-1
label=linux
root=/dev/hda1
read-only
other=/dev/hdb1
label=dos
map-drive = 0x80
to = 0x81
map-drive = 0x81
to = 0x80
#交换两硬盘主、从顺序
table=/dev/hdb
配置好lilo.conf文件后,在root账户下执行lilo命令,新的LILO就被载入系统。上面第一个例子执行结果如下:
#lilo
Added linux
Added dos*
Added sco
(注:带*号的表示其为缺省操作系统)
五、LILO提示信息
LILO在运行时会给出一些提示信息,了解它的含义对我们正确配置lilo.conf或查找硬件错误是有帮助的。
当LILO装入它自己的时候,显示单词 “LILO”:每完成一个特定的过程显示一个字母。如果LILO在某个地方失败了,屏幕上就停留几个字母,以指示错误发生的地方。
注意,如果磁盘发生瞬间故障,可能会在第一个字母“L”后插入一些十六进制数字(磁盘错误码)。除非LILO停在那里并不停地产生错误码流,否则并不说明有严重问题。
没有提示: LILO没有安装或者安装LILO的分区没有被激活。
L〈错误码〉 : LILO的第一部分已经被装入并运行了,但它不能装入第二部分的引导程序。两位数字的错误码指示问题的类型(参见“磁盘错误码”),这种情况通常是在介质访问失败或硬盘参数错误。
LI: LILO第一部分正确但是第二部分执行时出错。这一般是硬盘参数有误或/boot/boot.b被移动后没有重新运行map安装程序。
LIL: LILO第二部分开始执行,但是不能从“map”文件中读取描述符表( descriptor table)。 这通常是因介质错误或磁盘参数有误引起的。
LIL?: LILO在错误的地方加载。原因与“LI”大致相同。
LIL-:描述符表(descriptor table)错误。典型原因是硬盘几何参数微妙的不匹配或/boot/boot.b被移动而没有运行map安装程序。
LILO: LILO执行正确。
1010101010: 分区情况已经改变却没有重新安装LILO,另外,超频也可能会出这种情况。
六、磁盘错误码
0x00:“内部错误”。 由LILO扇区读取子程序产生。可能是因为被破坏的文件,重建map文件试试看。另一个原因也许是,当使用“linear”参数时去访问超出1024的柱面。
0x01:“非法命令”。这意味着LILO访问了BIOS不支持的硬盘。
0x02:“没找到地址标记”。通常是介质问题,多试几遍看看。
0x03:“写保护错”。 仅在写操作时出现。
0x04:“扇区未找到”。典型的原因是硬盘参数错误。
0x06:“激活顺序改变”。这应该是短暂的错误,再试一次。
0x07:“无效的初始化”。BIOS没有适当地初始化硬盘,热启动一次或许有帮助。
0x08:“DMA超出限度”。这不应当发生,重新启动。
0x09:“DMA试图越过64kB边界”。这不应当发生,建议忽略“compact”参数。
0x0C:“无效的介质”。这不应当发生,重新启动看看。
0x10:“CRC错误”。检测到介质错误。建议多启动几次,运行map安装程序,把map文件从坏块写到正常的介质上。
0x11:“ECC纠正成功”。读错误发生然后被纠正,但是LILO并不知道这个情况,终止了启动过程。
0x20:“控制器错误”。一般不应发生。
0x40:“定位失败”。这可能是介质问题,重新启动试试。
0x80:“磁盘超时”。磁盘或驱动器没有准备好。介质坏了或磁盘没有转,也有可能是从软盘启动而没有关上软驱门。
0xBB:“BIOS错误”。一般不应发生,如果反复发生,可考虑去掉“compact”参数或添加删除“linear”参数。
如果在写操作过程中发生错误,则在错误码前有个前缀“w”。尽管写错误并不影响启动过程,但它们暗示了系统中存在某种错误,建议重新配置LILO成只读格式(read-only)。
LILO的配置相当复杂,读者只有在实践中不断学习、摸索,勤于思考,才能用好LILO。
2. 支持不符合Multiboot标准的内核
GRUB能够直接支持多种并不符合Multiboot标准的自由操作系统内核(主要是FreeBSD,NetBSD,OpenBSD和 linux)。也能通过chainload间接引导非开放的其他操作系统。
3. 支持操作系统模块装载。
4. 提供文本格式可手工修改的配置文件。
5. 菜单界面
6. 灵活的命令行界面
7. 多文件系统识别
能够透明地识别多种文件系统,现在能够识别的文件系统有BSD FFS,DOS FAT16,FAT32和Linux ext2fs.这个范围仍然在扩展。
8. 支持压缩文件的解压缩。
能够解压缩被gzip压缩的文件,并且这个识别和解压过程是自动的和对用户透明的,这个功能大大地减少了文件的大小,减少了load的时间,这个功能对于软盘上的系统尤其有用。
可能有些内核模块在装载时要求是压缩状态,这时解压此模块可能会画蛇添足,所以GRUB提供了另一不进行解压缩的模块装载命令。
9. 可以读取任何已安装的设备上的数据
支持读取软盘,硬盘上的数据,不依赖于根设备上任何的设置。
10. 和磁盘定位的表示方法无关。
11. 能够使用BIOS所检测到的所有RAM.
GRUB通常能够找到PC兼容机上的全部RAM,它采用一种先进的BIOS查询技术来找到所有的内存空间。
12. 支持硬盘的LBA模式
GRUB通过支持LBA模式,突破1024柱面的限制,能够访问8GB以外的全部硬盘空间。
13. 支持网络
虽然GRUB是一个基于磁盘的引导程序,但是它也支持网络功能,你可以通过TFTP协议从网络上得到操作系统映象文件并引导。
GRUB的后继版本可能会包括一个内置的可编程语言来支持各种内核的引导参数,这还只是一个操作系统引导器吗?;),并且计划加入对非PC体系结构的支持。
你可以到<ftp://alpha.gnu.org/gnu/grub/grub-0.5.94.tar.gz>得到GRUB,然后:
zcat grub-0.5.94.tar.gz | tar xvf -
会生成一个目录grub-0.5.94,再:
cd grub-0.5.94
./configure
make install
这样GRUB就安装好了,下面你需要在你的硬盘或者软盘引导区上安装GRUB引导代码。
制作GRUB引导软盘:
cd /boot/grub
dd if=stage1 of=/dev/fd0 bs=512 count=1
dd if=stage2 of=/dev/fd0 bs=512 seek=1
制作GRUB硬盘引导:
重启动用GRUB引导软盘引导,或者你不想重启动也可以执行/usr/sbin/grub。两种情况都会进入命令行界面。 然后,我们首先要设置GRUB的“根设备”,也就是告诉GRUB安装所在的分区:
grub> root (hd0,0)
这里牵涉到GRUB的设备命名规则,将在下面介绍,此处(hd0,0)是指第一块硬盘的第一个分区。
如果你不能够确定安装GRUB所在的分区号的话,可以通过find指令查找:
grub> find /boot/grub/stage1
GRUB将会查找文件/boot/grub/stage1并显示包含这个文件的设备名,当然就是我们安装GRUB所在的分区。下面就可以写引导记录了:
grub> setup (hd0)
这条命令将会在第一块硬盘的MBR安装GRUB引导,如果你不想在MBR安装GRUB,而是希望将GRUB安装在分区的引导扇区的话,你可以用下面指令指定安装设备:
grub> setup (hd0,0)
这将会在第一块硬盘的第一个分区的引导扇区安装GRUB。
OK,现在你就可以重新启动由GRUB引导你的系统。
(fd0):第一软驱,GRUB还可以引导软盘上的操作系统:)
(hd0,1): 第一块硬盘的第二个分区。
(hd1,4): 第二块硬盘的第一个扩展分区,扩展的分区是从4开始编号的。
(hd0,2,a): 专用于FreeBSD,FreeBSD有一个slice概念,把一个分区进一步分为几个slice,此处指明是第一块硬盘的第三个分区中的slice a。你也可以用(hd0,a),这样GRUB就会在第一块硬盘上找到第一个FreeBSD分区的slice a。
让我们再来看看GRUB对于磁盘文件的命名方法:
(hd0,1)/vmlinuz,很简单只要指定分区号和文件的绝对路径名就可以了。
GNU/Linux
---------
grub> root (hd1,3)
grub> kernel /vmlinuz root=/dev/hda1
如果你需要指定内核启动参数的话,可以直接加到命令的最后面如:
grub> kernel /vmlinuz root=/dev/hda1 vga=ext
如果你使用initrd的话,在kernel命令之后执行:
grub> initrd /initrd
grub> boot
FreeBSD
-------
GRUB能够直接装载.ELF和a.out两种格式的内核,但是由于FreeBSD的内核引导接口有时有较大的变动,所以,对FreeBSD最安全的引导方法是引导/boot/loader
grub> root (hd0,a)
grub> kernel /boot/loader
grub> boot
NetBSD,OpenBSD,NetBSD
-------------------------------------
这三种系统的引导指令序列一样,如下:
1. 'root'设置根设备.
2. `kernel'装载内核.
3. `boot'引导.
DOS/Windows
-----------
grub> rootnoverify (hd0,0)
grub> chainloader +1
grub> boot
SCO UnixWare
------------
grub> rootnoverify (hd1,0)
grub> chainloader --force +1
grub> makeactive //注意这条指令将设置UnixWare分区为活动分区,这样要求你的GRUB安装在MBR,否则下次启动时将直接进入UnixWare而不会进入GRUB grub> boot
当然,如果每次引导都需要敲入命令的话实在是太麻烦了,因此,类似于LILO,GRUB提供了一个菜单方式,你需要一个配置文件将这些命令放入配置文件中就可以实现菜单方式的多引导,当然在菜单方式下你可以切换到命令模式下。GRUB引导时查找/boot/grub/menu.lst,如果存在这个文件的话,就根据这个文件生成一个引导菜单,menu.lst文件格式很简单。
map to_drive from_drive
映射驱动器from_drive到to_drive。这条指令当你在chainload一些操作系统的时候可能是必须的,这些操作系统如果不是在第一个硬盘上可能不能正常启动,所以需要进行映射。如下:
grub> map (hd0) (hd1)
grub> map (hd1) (hd0)
module file ...
对于符合Multiboot规范的操作系统可以用这条指令来装载模块文件file,file后可以跟这个module所需要的参数。注意,必须先装载内核,再装载模块,否则装载的模块无效。
modulenounzip file ...
同module命令几乎一样,唯一的区别是不对module文件进行自动解压。
pause message ...
输出字符串message,等待用户按任意键继续。你可以用<^G>(ASCII码007)使PC喇叭发声提醒用户注意。
quit
退出GRUB shell,GRUB shell类似于启动时的命令行模式,只是它是在用户启动系统后执行/sbin/grub才
进入,两者差别不大。
read addr
从内存的地址addr处读出32位的值并以十六进制显示出来。
root device [hdbias]
将当前根设备设为device,并且试图mount这个根设备得到分区大小。hdbias参数是用来告诉BSD内核在当前分区所在磁盘的前面还有多少个BIOS磁盘编号。例如,系统有一个IDE硬盘和一个SCSI硬盘,而你的BSD安装在IDE硬盘上,此时,你就需要指定hdbias参数为1。
rootnoverify device [hdbias]
和root类似,但是不mount该设备。这个命令用在当GRUB不能识别某个硬盘文件系统,但是仍然必须指定根设备。
setup install_device [image_device]
安装GRUB引导在install_device上。这条指令实际上调用的是更加灵活但是复杂的install指令。如果
image_device也指定了的话,则将在image_device中寻找GRUB的文件映象,否则在当前根设备中查找。
testload file
这条指令是用来测试文件系统代码的,它以不同的方式读取文件file的内容,并将得到的结果进行比较,如果正确的话,输出的`i=X,filepos=Y`中的X,Y的值应该相等,否则就说明有错误。通常这条指令正确执行的话,之后我们就可以正确无误地装载内核。
uppermem kbytes
强迫GRBU认为高端内存只有kbytes千字节的内存,GRUB自动探测到的结果将变得无效。这条指令很少使用,可能只在一些古老的机器上才有必要。通常GRUB都能够正确地得到系统的内存数量。
whatis rc
rc(8) - command scripts for auto-reboot and daemon startup
这些脚本实际位于/etc/rc;通常,位于/etc下的这个配置文件对应于手册的第五部分,所以你可以根据手册对配置文件作正确地修改。但是,如果你打:
man 5 rc
你却会得到以下信息:
No entry for rc in section 5 of the manual
这对于上面提到的它位于手册第八部分来说看起来有点古怪,因为这部分手册包含的是系统维护和操作命令,通常它们都是后台进程。让我们进一步来看一下这个文件:
more /etc/rc
# System startup script run by init on autoboot
# or after single-user.
# Output and error are redirected to console by init,
# and the console is the controlling terminal.
# Note that almost all of the user-configurable behavior
# is no longer in # this file, but rather in /etc/defaults/rc.conf.
# Please check that file first before contemplating any changes
# here. If you do need to change this file for some reason, we
# would like to know about it.
好,相当清晰;看来对于该文件我们自己是不能乱来的。这里有些相当重要的东西对于正确引导我们的系统所必须的。让我们往后跳,看一些重要的部分来找出启动时实际上都发生了些什么。注意当在引导过程中处理rc脚本时,init会把所有的输出和错误信息记录到终端上。
rc首先做的事之一就是设置路径变量,以使它可以找到你FreeBSD系统上的可执行程序:
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin
然后它会查找/etc/defaults/rc.conf and和/etc/rc.conf这两个文件:
# If there is a global system configuration file, suck it in.
if [ -f /etc/defaults/rc.conf ]; then
. /etc/defaults/rc.conf
elif [ -f /etc/rc.conf ]; then
. /etc/rc.conf
fi
接着它会作一个文件系统连贯性检查。如果你曾经非正常关闭FreeBSD系统,你会在引导过程中看到它在这一步上发出抱怨的。
echo Automatic boot in progress...
fsck -p
假定fsck没有遇到任何问题,它就马上装载你的文件系统:
# Mount everything except nfs filesystems.
mount -a -t nonfs
在其它任何进程启动之前,你的CMOS时钟必须调整为内核时钟可以理解的形式:
adjkerntz -i
然后整理var目录,将引导信息写入dmesg.boot:
clean_var() {
if [ ! -f /var/run/clean_var ]; then
rm -rf /var/run/*
find /var/spool/lock ! -type d -delete
rm -rf /var/spool/uucp/.Temp/*
# Keep a copy of the boot messages around
dmesg >/var/run/dmesg.boot
接着rc会读取以下文件:
/etc/rc.sysctl
/etc/rc.serial
/etc/rc.pccard
/etc/rc.network
/etc/rc.network6
然后复位终端权限:
# Whack the pty perms back into shape.
chflags 0 /dev/tty[pqrsPQRS]*
chmod 666 /dev/tty[pqrsPQRS]*
chown root:wheel /dev/tty[pqrsPQRS]*
并清理自己产生的“垃圾”以及/tmp目录:
# Clean up left-over files
# Clearing /tmp at boot-time seems to have a long tradition. It doesn't
# help in any way for long-living systems, and it might accidentally
# clobber files you would rather like to have preserved after a crash
# (if not using mfs /tmp anyway).
# See also the example of another cleanup policy in /etc/periodic/daily.
# Remove X lock files, since they will prevent you from restarting X11
# after a system crash.
现在rc准备启动一些后台进程,首先是syslogd和named:
# Start system logging and name service. Named needs to start before syslogd
# if you don't have a /etc/resolv.conf.
然后是inetd、cron、lpd、sendmail、sshd和usbd:
# Now start up miscellaneous daemons that don't belong anywhere else
接着rc将更新motd(每日信息)并执行“uname -m”,这条命令会在屏幕上显示构架类型。(/etc/rc文件结尾)
当到达/etc/rc的结尾时,rc的工作就完成了。在此我们重新回顾一下:init调用rc脚本,它会读取一些全局的和本地的配置文件以正确装载文件系统并建立系统后台进程可以启动的环境。你的操作系统现在已经启动并运行着,但到此为止,还没有一个用户可以与操作系统实际交互的环境。这就是init第二个重要的功能。
配置文件/etc/ttys将会被读取以决定初始化的终端。不象/etc/rc,该文件可以由超级用户经常编辑以确保让init来初始化所需的终端。为了理解此文件,我们必须了解在你的FreeBSD系统上有三种类型的终端。以“ttyv”开头后跟一个数字的是虚拟终端;它们都是用户可以获得的物理存在于FreeBSD系统上的终端。缺省情况下,这些虚拟终端中的第一个,或叫“ttyv0”,表示控制台。以“ttyd”开头后跟一个数字的是串行线路或拨号终端;它们是用户用调制解调器远程访问你的FreeBSD系统时可获得的终端。最后一种终端类型就是伪终端或网络终端;它们以“ttyp”开头后跟一个数字或字母,用于通过网络连接访问你的FreeBSD系统。
如果我们用以下命令看此文件:
more /etc/ttys
我们会看到此文件分为三部分,每个部分分别对应这三种类型的终端。同时每个部分还分为四栏,总结为下面的图表:
栏名 含义
name 终端设备的名称
getty 在终端上启动运行的程序,通常为getty。其它项目包括xdm,它用来启动X Window系
统,或none,说明没有程序。
type 对于虚拟终端,对应的类型为cons25。其它通常的值包括伪终端network,调制解调
器入口dialup,以及unknown,用于用户试图以无法预定的类型进行连接的终端。
status 它必须是on或off。如果是on,init将运行getty栏指定的程序。如果出现单词
“secure”,说明该tty允许root登录;为避免这种情况,可以用单词
“insecure”。
让我们从虚拟终端部分开始解释该文件;可以看到它是以设置控制台开始的:
# If console is marked "insecure", then init will ask
# for the root password when going to single-user mode.
console none unknown off secure
如果在引导过程中fsck命令运行出了问题,init将使你的FreeBSD系统进入单用户模式以使root用户可以修复问题。如果你用insecure代替secure来设置控制台,init将在你可以继续干之前索取口令。
ttyv0 "/usr/libexec/getty Pc" cons25 on secure
# Virtual terminals
ttyv1 "/usr/libexec/getty Pc" cons25 on secure
ttyv2 "/usr/libexec/getty Pc" cons25 on secure
ttyv3 "/usr/libexec/getty Pc" cons25 on secure
ttyv4 "/usr/libexec/getty Pc" cons25 on secure
ttyv5 "/usr/libexec/getty Pc" cons25 on secure
ttyv6 "/usr/libexec/getty Pc" cons25 on secure
ttyv7 "/usr/libexec/getty Pc" cons25 on secure
ttyv8 "/usr/X11R6/bin/xdm -nodaemon" xterm off secure
你可以看到在我的FreeBSD系统上除了控制台以外还有八个虚拟终端;我可以通过按ALT键加一个控制键来访问每个终端。例如ALT F1可访问控制台,ALT F2访问ttyv1, ALT F3访问ttyv2,等等。如果我启动了X会话,那么它可以用ALT F8来访问。如果我把ttyv8上的单词off改为on,那么我可以在引导时得到一个X终端而不是控制台。然后可以继续用我ALT加功能键来访问其它终端。我的所有这些虚拟终端都标为“secure”,说明它们都可接受root登录。你可以有多少个虚拟终端是由你的FreeBSD版本所决定的;如果你希望建立更多虚拟终端,可
以读一下这个faq。
现在让我们移到拨号终端:
# Serial terminals
# The 'dialup' keyword identifies dialin lines to login, fingerd etc.
ttyd0 "/usr/libexec/getty std.9600" dialup off secure
ttyd1 "/usr/libexec/getty std.9600" dialup off secure
ttyd2 "/usr/libexec/getty std.9600" dialup off secure
ttyd3 "/usr/libexec/getty std.9600" dialup off secure
你可以看到我有四个可获得的拨号终端,但它们都被关闭了。如果我想让用户通过调制解调器访问我的FreeBSD系统,我就必须至少打开它们中的一个,还必须决定是否让这些用户可以用root身份登录;如果不,就把单词“secure”改为“insecure”。你是否看到getty栏含有数字9600,它说明数据传输率为9600bps。因为现在很多调制解调器都有更高的速率,我也可以把它改为57600。最后,最好读一下FreeBSD handbook中的拨号服务部分。/etc/ttys文件的最后一部分是网络或伪终端。你会看到它们有很多,准确地说是255个,范
围从:
# Pseudo terminals
ttyp0 none network
到
ttySv none network
且缺省情况下它们都没有被允许。
如果你为了使/etc/ttys更改生效以使init使用这些更改,可以超级用户的身份向init发送一个HUP信号,如:
kill -1 1
这里前面的-1代表信号1(HUP),而后面1代表进程1(init)。
那么现在,哪个/etc/ttys文件中提到的getty程序继续保持运行呢?man 8中对getty的描述如下:
描述
init(8)调用getty程序打开并初始化tty行,读取一个登录名,然后调用login(1)。所以,init读取/etc/ttys并在每个你在配置文件中设定的终端上启动一个getty进程。getty的工作是监视终端看是否有人试图登录。如果有的话,getty将启动登录程序校验用户的登录名和口令。如果校验合格,登录程序会启动用户的登录命令解释器并把用户置于他们的宿主目录下。当用户具有一个命令解释器后,他们就可以与操作系统交互了。现在它就可以让命令解释器解释用户的输入并确保启动了必要的进程。
当一个用户退出登录时,再次调用init启动其它的getty进程以继续监视终端等待其它的登录尝试让我们看一下ps命令的输出来总结一下刚才这次引导的整个过程,FreeBSD 4.1缺省已经安装了ps程序。我将用-ax开关以包含系统进程:
ps -ax
PID TT STAT TIME COMMAND
0 ?? DLs 0:00.01 (swapper)
1 ?? ILs 0:00.16 /sbin/init --
2 ?? DL 0:00.02 (pagedaemon)
3 ?? DL 0:00.00 (vmdaemon)
4 ?? DL 0:00.02 (bufdaemon)
5 ?? DL 0:01.02 (syncer)
1056 ?? Is 0:00.00 adjkerntz -i
1187 ?? Ss 0:00.08 syslogd -s
1206 ?? Is 0:00.05 inetd -wW
1208 ?? Is 0:00.11 cron
1622 ?? Ss 0:00.02 sendmail: accepting connections on port 25 (sendmail)
1621 v0 Ss 0:00.12 -csh (csh)
1701 v0 R+ 0:00.00 ps -ax
1699 v1 Is+ 0:00.01 /usr/libexec/getty Pc ttyv1
1619 v2 Is+ 0:00.01 /usr/libexec/getty Pc ttyv2
1618 v3 Is+ 0:00.01 /usr/libexec/getty Pc ttyv3
1617 v4 Is+ 0:00.01 /usr/libexec/getty Pc ttyv4
1616 v5 Is+ 0:00.01 /usr/libexec/getty Pc ttyv5
1615 v6 Is+ 0:00.01 /usr/libexec/getty Pc ttyv6
1614 v7 Is+ 0:00.01 /usr/libexec/getty Pc ttyv7
现在你可以认识很多进程:swapper的PID为0而init的为1。adjkerntz,syslogd,inetd,cron和sendmail都是由rc启动的。当然,我必须在一个命令解释器上运行这个ps命令;在上述情况中,它是从ttyv0上的c shell解释器运行的。getty进程等待虚拟终端1-7上的登录。而在虚拟终端8上则没有运行getty进程,因为该终端在/etc/ttys中被标为了“off”。
标题:/etc/rc?.d目录和/etc/rc?文件分析
运行级0-6分别对应着一个/etc/rc?.d目录和一个/etc/rc?文件。rc?文件是个shell script,从/etc/inittab文件分析中可以看到,当进入运行级?时,rc?文件就会得到执行。从上面的示例文件中看到缺省实际运行级是3,注意到rc2也被执行了,下面是rc2示例
#!/sbin/sh
PATH=/usr/sbin:/usr/bin
set `/usr/bin/who -r`
if [ x$9 = "xS" -o x$9 = "x1" ]
then
echo 'The system is coming up. Please wait.'
BOOT=yes
elif [ x$7 = "x2" ]
then
echo 'Changing to state 2.'
if [ -d /etc/rc2.d ]
then
for f in /etc/rc2.d/K*
{
if [ -s ${f} ]
then
case ${f} in
*.sh) . ${f} ;;
*) /sbin/sh ${f} stop ;;
esac
fi
}
fi
fi
if [ x$9 != "x2" -a x$9 != "x3" -a -d /etc/rc2.d ]
then
for f in /etc/rc2.d/S*
{
if [ -s ${f} ]
then
case ${f} in
*.sh) . ${f} ;; # source it
*) /sbin/sh ${f} start ;; # sub shell
esac
fi
}
fi
#if [ ! -s /etc/rc2.d/.ports.sem ]
#then
# /sbin/ports
# echo "ports completed" > /etc/rc2.d/.ports.sem
#fi
# Start historical section.
if [ "${BOOT}" = "yes" -a -d /etc/rc.d ]
then
for f in `/usr/bin/ls /etc/rc.d`
{
if [ ! -s /etc/init.d/${f} ]
then
/sbin/sh /etc/rc.d/${f}
fi
}
fi
# End historical section.
if [ "${BOOT}" = "yes" -a x$7 = "x2" ]
then
echo 'The system is ready.'
elif [ x$7 = "x2" ]
then
echo 'Change to state 2 has been completed.'
fi
可以看到,rc2的主要任务是启动或终止/etc/rc2.d目录下的相关文件,这些文件也是shell script文件。这些文件具有如下格式:S??name或者K??nameK表示当进入运行级2时需执行此文件以终止某些进程,S表示当进入运行级2时需执行此文件以启动某些进程。??是00-99的数字,代表了终止和启动的顺序。name对应一个文件名,通常是/etc/init.d/name,注意这实际是些硬链接。
init进程就是所谓1号进程,用ps -jfl -p 1就可以看到全貌。init在启动中会读取/etc/inittab,处理如下:
1. 查找initdefault项,存在则以相应运行级启动,不存在系统将要求输入运行级,若输入S或s将进入单用户状态。
2. 启动后,若系统首次进入除单用户以外的其他状态,init将在/etc/inittab中查找boot或bootwait项,存在则启动相关进程,然后再启动当前运行级下的其他进程。
3. init创建完所有子进程后进入循环等待,并不消亡。init q或者telinit Q将导致init重新读取/etc/inittab文件
4. 虚拟运行级a、b、c必须通过init a直接启动相关进程,不会改变当前运行级,这种进程在系统切换运行级时不会被终止,只有遇到下列情况才被终止:
a. 该项action域被标记为OFF
b. 该项被删除
c. 进入单用户状态
5. 运行级
0 停机;shutdown实际上最后做了init 0
1 系统管理状态;若从常规运行级进入本运行级,不终止任何服务和进程,所以没有意义。只有从S级进入才有意义。S或s 单用户状态;最严格状态,与系统之间只能通过主控台进行交互。
6 正常停机并重新启动,进入initdefault项指定的运行级a、b、c 虚拟运行级,用于在不改变当前运行级的情况下启动进程Q或q 通过init q引起对/etc/inittab的重新检测
6. 文件每行的格式
id:rstate:action:process
id 两个字符,不得重复
rstate 该项应该被处理的运行级;可以指定多个运行级,0-6任意组合。为空表示所有运行级。切换运行级时,init会检查所有进程,如果进程相关rstate域中无新运行级,该进程收到SIGTERM信号,5秒后被强行终止。
action
respawn 进程不存在就启动,启动进程后不等待进程终止。一旦进程终止就再次启动。
进程已经存在则继续扫描/etc/inittab文件
wait 如果系统正在进入的运行级在该项的rstate域已经指定,则启动该进程,并等待进程终止。
以后再次扫描/etc/inittab时,若运行级没有改变,则忽略本项。
once 如果系统正在进入的运行级在该项的rstate域已经指定,则启动该进程,但不等待进程终
止。进程终止后也不再次启动。切换到新运行级时,若该进程已经存在,也不再重新启动它。
boot 只在系统启动过程中被处理。启动进程后不等待进程终止,进程终止后也不再次启动它。
当这里指定boot时,相关rstate应该设置成系统缺省实际运行级。该项主要用于冷启动
bootwait 系统启动后首次从单用户切换到常规运行级时被处理。启动进程并等待进程终止。
powerfail 当系统接收到掉电信号时启动相关进程powerwait 当系统接收到掉电信号时启动相关进程,
并等待进程终止,在进程终止前不做任何其它操作。
off 若该项相关进程已经存在则强行终止,否则忽略。
ondemand 功能同respawn,但只用于虚拟运行级
initdefault 只在系统首次启动init时被处理。注意,如果rstate为空,等同于将rstate指定为0123456,
此时init将引导系统进入最高运行级,实际上就是init 6,其结果是系统无休止的重启动。
另外,如果对应的rstate设置成0或者1,将导致系统无法正常启动,切记。
sysinit 在系统激活主控台前执行(即主控台显示login:提示之前),并等待进程终止,一般用于设备初始化。
process 格式遵从sh语法
下面是solaris2.5.1下的一个示例文件
ap::sysinit:/sbin/autopush -f /etc/iu.ap
fs::sysinit:/sbin/rcS >/dev/console 2>&1 </dev/console
is:3:initdefault:
p3:s1234:powerfail:/usr/sbin/shutdown -y -i5 -g0 >/dev/console 2>&1
s0:0:wait:/sbin/rc0 >/dev/console 2>&1 </dev/console
s1:1:wait:/usr/sbin/shutdown -y -iS -g0 >/dev/console 2>&1 </dev/console
s2:23:wait:/sbin/rc2 >/dev/console 2>&1 </dev/console
s3:3:wait:/sbin/rc3 >/dev/console 2>&1 </dev/console
s5:5:wait:/sbin/rc5 >/dev/console 2>&1 </dev/console
s6:6:wait:/sbin/rc6 >/dev/console 2>&1 </dev/console
fw:0:wait:/sbin/uadmin 2 0 >/dev/console 2>&1 </dev/console
of:5:wait:/sbin/uadmin 2 6 >/dev/console 2>&1 </dev/console
rb:6:wait:/sbin/uadmin 2 1 >/dev/console 2>&1 </dev/console
sc:234:respawn:/usr/lib/saf/sac -t 300
co:234:respawn:/usr/lib/saf/ttymon -g -h -p "`uname -n` \
console login: " -T sun -d /dev/console -l console -m ldterm,ttcompat
一个修改/etc/inittab的实例
假设/dev/tty00是个串口,想在这个串口上挂一个终端
1. 用RS232标准串行线连接串口和终端,终端上电,设置终端参数9600 7 偶校验
2. 主机上电,root注册,修改/etc/inittab,增加一行
00:23:respawn:/sbin/getty tty00 9600
3. init q
amd:自动安装NFS(网络文件系统)守侯进程
apmd:高级电源管理
Arpwatch:记录日志并构建一个在LAN接口上看到的以太网地址和IP地址对数据库
Autofs:自动安装管理进程automount,与NFS相关,依赖于NIS
Bootparamd:引导参数服务器,为LAN上的无盘工作站提供引导所需的相关信息
crond:Linux下的计划任务
Dhcpd:启动一个DHCP(动态IP地址分配)服务器
Gated:网关路由守候进程,使用动态的OSPF路由选择协议
Httpd:WEB服务器
Inetd:支持多种网络服务的核心守候程序
Innd:Usenet新闻服务器
Linuxconf:允许使用本地WEB服务器作为用户接口来配置机器
Lpd:打印服务器
Mars-nwe:mars-nwe文件和用于Novell的打印服务器
Mcserv:Midnight命令文件服务器
named:DNS服务器
netfs:安装NFS、Samba和NetWare网络文件系统
network:激活已配置网络接口的脚本程序
nfs:打开NFS服务
nscd:nscd(Name Switch Cache daemon)服务器,用于NIS一个支持服务,它高速缓存用户口令和组成成员关系
portmap:RPC portmap管理器,与inetd类似,它管理基于RPC服务的连接
postgresql:一种SQL数据库服务器
routed:路由守候进程,使用动态RIP路由选择协议
rstatd:一个为LAN上的其它机器收集和提供系统信息的守候程序
ruserd:远程用户定位服务,这是一个基于RPC的服务,它提供关于当前记录到LAN上一个机器日志中的用户信息
rwalld:激活rpc.rwall服务进程,这是一项基于RPC的服务,允许用户给每个注册到LAN机器的其他终端写消息
rwhod:激活rwhod服务进程,它支持LAN的rwho和ruptime服务
sendmail:邮件服务器sendmail
smb:Samba文件共享/打印服务
snmpd:本地简单网络管理候进程
squid:激活代理服务器squid
syslog:一个让系统引导时起动syslog和klogd系统日志守候进程的脚本
xfs:X Window字型服务器,为本地和远程X服务器提供字型集
xntpd:网络时间服务器
ypbind:为NIS(网络信息系统)客户机激活ypbind服务进程
yppasswdd:NIS口令服务器
ypserv:NIS主服务器
gpm:管鼠标的
identd:AUTH服务,在提供用户信息方面与finger类似
1. 硬盘参数释疑
到目前为止, 人们常说的硬盘参数还是古老的 CHS (Cylinder/Head/Sector)参数. 那么为什么要使用这些参数, 它们的意义是什么?它们的取值范围是什么?
很久以前, 硬盘的容量还非常小的时候, 人们采用与软盘类似的结构生产硬盘. 也就是硬盘盘片的每一条磁道都具有相同的扇区数. 由此产生了所谓的3D参数 (Disk Geometry). 既磁头数(Heads), 柱面数
(Cylinders), 扇区数(Sectors per track),以及相应的寻址方式.
其中:
磁头数(Heads) 表示硬盘总共有几个磁头,也就是有几面盘片, 最大为 256 (用 8 个二进制位存储);
柱面数(Cylinders) 表示硬盘每一面盘片上有几条磁道, 最大为 1024(用 10 个二进制位存储);
扇区数(Sectors per track) 表示每一条磁道上有几个扇区, 最大为63 (用 6 个二进制位存储).
每个扇区一般是 512个字节, 理论上讲这不是必须的, 但好象没有取别的值的.
所以磁盘最大容量为:
256 * 1024 * 63 * 512 / 1048576 = 8064 GB ( 1M = 1048576 Bytes )或硬盘厂商常用的单位:
256 * 1024 * 63 * 512 / 1000000 = 8455 GB ( 1M = 1000000 Bytes )
在 CHS 寻址方式中, 磁头, 柱面, 扇区的取值范围分别为 0 到 Heads-1,0 到 Cylinders-1, 1 到 Sectors per track (注意是从 1 开始).
在 CHS 寻址方式中, 有以下几种尺寸单位:
扇区 (Sector) = 512 字节 (一般情况下)
磁道 (Track) = (Sectors per track) 扇区
柱面 (Cylinder)= (Sectors per track) * Heads 扇区
2. 基本 Int 13H 调用简介
BIOS Int 13H 调用是 BIOS 提供的磁盘基本输入输出中断调用, 它可以完成磁盘(包括硬盘和软盘)的复位, 读写, 校验, 定位, 诊断, 格式化等功能.它使用的就是 CHS 寻址方式, 因此最大识能访问 8 GB 左右的硬盘 ( 本文中如不作特殊说明, 均以 1M = 1048576 字节为单位).
3. 现代硬盘结构简介
在老式硬盘中, 由于每个磁道的扇区数相等, 所以外道的记录密度要远低于内道, 因此会浪费很多磁盘空间 (与软盘一样). 为了解决这一问题, 进一步提高硬盘容量, 人们改用等密度结构生产硬盘. 也就是说, 外圈磁道的扇区比内圈磁道多. 采用这种结构后, 硬盘不再具有实际的3D参数, 寻址方式也改
为线性寻址, 即以扇区为单位进行寻址.
为了与使用3D寻址的老软件兼容 (如使用BIOS Int13H接口的软件), 在硬盘控制器内部安装了一个地址翻译器, 由它负责将老式3D参数翻译成新的线性参数. 这也是为什么现在硬盘的3D参数可以有多种选择的原因 (不同的工作模式, 对应不同的3D参数, 如 LBA, LARGE, NORMAL).
4. 扩展 Int 13H 简介
虽然现代硬盘都已经采用了线性寻址, 但是由于基本 Int 13H 的制约, 使用 BIOS Int 13H 接口的程序, 如 DOS 等还只能访问 8 G 以内的硬盘空间.为了打破这一限制, Microsoft 等几家公司制定了扩展 Int 13H 标准(Extended Int13H), 采用线性寻址方式存取硬盘, 所以突破了 8 G 的限制,而且还加入了对可拆卸介质 (如活动硬盘) 的支持.
(http://www.phoenix.com/products/specs.html)
二. Boot Sector 结构简介
1. Boot Sector 的组成
Boot Sector 也就是硬盘的第一个扇区, 它由 MBR (Master Boot Record),DPT (Disk Partition Table) 和 Boot Record ID 三部分组成.
MBR 又称作主引导记录,占用 Boot Sector 的前 446 个字节 ( 0 to 0x1BD ),存放系统主引导程序 (它负责从活动分区中装载并运行系统引导程序).
DPT 即主分区表占用 64 个字节 (0x1BE to 0x1FD), 记录了磁盘的基本分区信息. 主分区表分为四个分区项, 每项 16 字节, 分别记录了每个主分区的信息(因此最多可以有四个主分区).
Boot Record ID 即引导区标记占用两个字节 (0x1FE and 0x1FF), 对于合法引导区, 它等于 0xAA55, 这是判别引导区是否合法的标志.
Boot Sector 的具体结构如下图所示:
0000 |------------------------------------------------|
| |
| |
| Master Boot Record |
| |
| |
| 主引导记录(446字节) |
| |
| |
| |
01BD | |
01BE |------------------------------------------------|
| |
01CD | 分区信息 1(16字节) |
01CE |------------------------------------------------|
| |
01DD | 分区信息 2(16字节) |
01DE |------------------------------------------------|
| |
01ED | 分区信息 3(16字节) |
01EE |------------------------------------------------|
| |
01FD | 分区信息 4(16字节) |
|------------------------------------------------|
| 01FE | 01FF |
| 55 | AA |
|------------------------------------------------|
2. 分区表结构简介
分区表由四个分区项构成, 每一项的结构如下:
BYTE State : 分区状态, 0 = 未激活, 0x80 = 激活 (注意此项)
BYTE StartHead : 分区起始磁头号
WORD StartSC : 分区起始扇区和柱面号, 底字节的低6位为扇区号,
高2位为柱面号的第 9,10 位, 高字节为柱面号的低 8 位
BYTE Type : 分区类型, 如 0x0B = FAT32, 0x83 = Linux 等,
00 表示此项未用
BYTE EndHead : 分区结束磁头号
WORD EndSC : 分区结束扇区和柱面号, 定义同前
DWORD Relative : 在线性寻址方式下的分区相对扇区地址
(对于基本分区即为绝对地址)
DWORD Sectors : 分区大小 (总扇区数)
注意: 在 DOS / Windows 系统下, 基本分区必须以柱面为单位划分( Sectors * Heads 个扇区), 如对于 CHS 为 764/256/63 的硬盘, 分区的最小尺寸为 256 * 63 * 512 / 1048576 = 7.875 MB.
由于硬盘的第一个扇区已经被引导扇区占用, 所以一般来说, 硬盘第一个磁道(0头0道)的其余 62 个扇区是不会被分区占用的. 某些分区软件甚至将第一个柱面全部空出来.
3. 扩展分区简介
由于主分区表中只能分四个分区, 无法满足需求, 因此设计了一种扩展分区格式. 基本上说, 扩展分区的信息是以链表形式存放的, 但也有一些特别的地方.
首先, 主分区表中要有一个基本扩展分区项, 所有扩展分区都隶属于它,也就是说其他所有扩展分区的空间都必须包括在这个基本扩展分区中. 对于DOS / Windows 来说, 扩展分区的类型为 0x05 或 0x0F (LBA模式).
除基本扩展分区以外的其他所有扩展分区则以链表的形式级联存放, 后一个扩展分区的数据项记录在前一个扩展分区的分区表中, 但两个扩展分区的空间并不重叠.
扩展分区类似于一个完整的硬盘, 必须进一步分区才能使用. 但每个扩展分区中只能存在一个其他分区. 此分区在 DOS/Windows 环境中即为逻辑盘.因此每一个扩展分区的分区表 (同样存储在扩展分区的第一个扇区中)中最多只能有两个分区数据项(包括下一个扩展分区的数据项).
扩展分区和逻辑盘的示意图如下:
|-----------------------| --------
| 主扩展分区(/dev/hda2) | ^
|-----------------------| |
| 扩 展 | 分区项 1 |--\ |
| |------------| | |
| 分区表 | 分区项 2 |--+--\ |
|-----------------------| | | |
| | | | |
| 逻辑盘 1 (/dev/hda5) |<-/ | |
| | | |
|-----------------------| | 主
| 扩展分区 2 |<----/
|-----------------------| 扩
| 扩 展 | 分区项 1 |--\
| |------------| | 展
| 分区表 | 分区项 2 |--+--\
|-----------------------| | | 分
| | | |
| 逻辑盘 2 (/dev/hda6) |<-/ | 区
| | | |
|-----------------------| | |
| 扩展分区 3 |<----/ |
|-----------------------| |
| 扩 展 | 分区项 1 |--\ |
| |------------| | |
| 分区表 | 分区项 2 | | |
|-----------------------| | |
| | | |
| 逻辑盘 3 (/dev/hda7) |<-/ |
| | |
|-----------------------| ---------
注意, 以上所有扩展分区表中的第二个分区项(指向下一个扩展分区)的相对扇区地址均相对于主扩展分区, 而不是前一个扩展分区.
三. 系统启动过程简介
系统启动过程主要由一下几步组成(以硬盘启动为例):
1. 开机 :-)
2. BIOS 加电自检 ( Power On Self Test -- POST )
内存地址为 0ffff:0000
3. 将硬盘第一个扇区 (0头0道1扇区, 也就是Boot Sector)
读入内存地址 0000:7c00 处.
4. 检查 (WORD) 0000:7dfe 是否等于 0xaa55, 若不等于
则转去尝试其他启动介质, 如果没有其他启动介质则显示
"No ROM BASIC" 然后死机.
5. 跳转到 0000:7c00 处执行 MBR 中的程序.
6. MBR 首先将自己复制到 0000:0600 处, 然后继续执行.
7. 在主分区表中搜索标志为活动的分区. 如果发现没有活动
分区或有不止一个活动分区, 则停止.
8. 将活动分区的第一个扇区读入内存地址 0000:7c00 处.
9. 检查 (WORD) 0000:7dfe 是否等于 0xaa55, 若不等于则
显示 "Missing Operating System" 然后停止, 或尝试
软盘启动.
10. 跳转到 0000:7c00 处继续执行特定系统的启动程序.
11. 启动系统 ...
以上步骤中 2,3,4,5 步是由 BIOS 的引导程序完成. 6,7,8,9,10步由MBR中的引导程序完成.
一般多系统引导程序 (如 SmartBootManager, BootStar, PQBoot 等)都是将标准主引导记录替换成自己的引导程序, 在运行系统启动程序之前让用户选择要启动的分区.
而某些系统自带的多系统引导程序 (如 lilo, NT Loader 等)则可以将自己的引导程序放在系统所处分区的第一个扇区中, 在 Linux中即为 SuperBlock (其实 SuperBlock 是两个扇区).
注: 以上各步骤中使用的是标准 MBR, 其他多系统引导程序的引导过程与此不同.
如果你的计算机上没有安装任何操作系统,请首先安装 Windows,然后再安装 Red Hat Linux。可以为 Windows 创建一个指定大小的分区。在硬盘驱动器上保留足够的空闲空间(没有被分区或格式化的分区)来安装 Linux。
如果你想要安装 Red Hat Linux 的计算机上目前运行的是 Windows (或某种其它操作系统),你需要做出一项重要决定。 你的选择是:
·已安装了 Windows,但是让Red Hat Linux代替它成为唯一操作系统吗?如果答案是肯定的,你没必要配置双引导系统。把想保留的信息全部备份,然后开始安装。在安装中,如果你在「磁盘分区设置」 屏幕中选定要安装程序自动为你的系统分区,请选择「删除系统上所有分区」。如果你选择要用 Disk Druid 或 fdisk 来手工分区,删除所有现存的 DOS (Windows) 分区,然后创建你的 Linux 分区。
·你想安装 Red Hat Linux ,然后既可以引导 Red Hat Linux 又可以引导你的另一个操作系统吗?执行此类 Red Hat Linux 安装可以在你的系统上安装 Red Hat Linux 却又不影响另一个操作系统。既然你已经装有 Windows,你需要:先为Linux分配磁盘空间,然后再在双引导环境中安装 Red Hat Linux。这就是后面两节的内容。
如果你在系统上已安装了 Windows,你必须有可用的空闲空间才能在其中安装 Red Hat Linux。可供选择的方法有:
·添加一个新硬盘。
·使用一个现存的硬盘或分区。
·创建一个新分区。
添加新硬盘驱动器为 Red Hat Linux 腾出空间的最简单办法是给计算机添加一个新硬盘驱动器,然后在该驱动器上安装 Red Hat Linux。例如,如果你给计算机添加了第二个 IDE 硬盘驱动器,Red Hat Linux 安装程序将会把它识别为 hdb,而把现存的驱动器 (被 Windows 使用的)识别为 hda。(对于 SCSI 硬盘驱动器,新安装的 Red Hat Linux 硬盘驱动器将会被识别为 sdb,而现存的硬盘驱动器将会被识别为 sda。)
如果你选择要为 Linux 安装新硬盘,你该做的只是启动 Red Hat Linux 安装程序。启动 Red Hat Linux 安装程序之后,请确定你选定的是在新安装的硬盘驱动器上安装 Linux (例如 hdb 或者 sdb)而不是在被 Windows 使用的硬盘驱动器上安装。
使用现存硬盘驱动器或分区另一种为 Linux 腾出空间的办法是,使用目前被 Windows 使用的磁盘驱动器或分区。例如,假设 Windows 资源管理器 显示了两个硬盘驱动器, C: 和 D:。这可能表明计算机有两个硬盘驱动器,或一个带有两个分区的硬盘驱动器。在以上任何情况下,(假设硬盘驱动器上有足够的磁盘空间),你都可以在 Windows 识别为 D: 的硬盘驱动器或磁盘分区上安装 Red Hat Linux 。
在你的计算机上有两个硬盘驱动器或磁盘分区时,可以利用一个你想在其中安装 Linux 的本地 Windows 分区,请执行下列步骤:
将所有选定硬盘驱动器或分区上(在这个例子中是 D: )你想保留的数据都复制到另外一个地方。
启动 Red Hat Linux 安装程序,然后令其在指定的分区或驱动器上安装 Linux - 在这个例子中,硬盘驱动器或分区被 Windows 标为 D:。请注意,Linux 区分硬盘驱动器和磁盘分区。因此:
如果在这台计算机上的 C: 和 D: 是指两个分开的硬盘驱动器,安装程序将会把它们识别为 hda 和 hdb (IDE) 或 sda 和 sdb (SCSI)。请通知安装程序在 hdb 还是 sdb 上安装。
如果 C: 和 D: 是指一个单个驱动器上的两个分区,安装程序将会把它们识别为 hda1 和 hda2 (或 sda1 和 sda2)。你可以在 Red Hat Linux 安装过程中的分区阶段删除第二个分区 (hda2 或 sda2),然后 为 Linux 拨发未分配的空闲空间。在开始安装 Red Hat Linux 之前,你不必删除第二个分区。
创建新分区第三种为 Linux 腾出空间的办法是在被其它操作系统使用的硬盘驱动器中为 Red Hat Linux 创建一个新分区。如果 Windows 资源管理器 只显示了一个硬盘驱动器 (C:),而且你不想添加新硬盘驱动器,那么,你就必须为硬盘分区。分区后, Windows 资源管理器 将会看到一个较小的 C: 驱动器,然后,当你运行 Red Hat Linux 安装程序的时候,你可以用驱动器的剩余空间来为 Linux 分区。
你可以使用一个破坏性的分区程序,例如 fdisk,来分隔硬盘驱动器,但是这么做之后, 你将需要重装 Windows。(这可能是你的最佳选择。)
当你运行到了 「磁盘分区设置」 屏幕中时,磁盘分区安装程序中的 「磁盘分区设置」 屏幕中有几个选项。根据你的选择而定,配置双引导系统的方法也有所不同。
(如果不知道要创建多少个 Linux 分区,推荐:
·等于内存容量两倍的 /swap 分区, - /swap 分区用来支持虚拟内存。换句话说,当没有足够的内存来容纳你的系统正在处理的数据时,这些数据就被写入 /swap。你的交换分区的最小值应该相当于你的计算机内存的两倍和32MB中较大的一个值。
·75MB的 /boot 分区 - 这个挂载在 /boot 上的分区包含操作系统的内核(允许你的系统引导Red Hat Linux),以及其它几个在引导过程中使用的文件。对大多数用户来说,75MB引导分区应该是足够了。警告:不要把 /boot 分区创建为LVM类型。
·1.5到4.5 GB的 / 分区 - 这是“/”,即根目录,除了贮存在 /boot 分区上的以外所有文件都位于根分区上。个人桌面或工作站需要硬盘空间为1.5 GB,安装全部软件需要4.5 GB。)
如果你选择:
·自动分区 - 选择「保留所有分区,使用现有空闲空间」。这一选项将会在你的硬盘驱动器上保留你的 Windows 分区,而使用空闲空间或附加硬盘驱动器为 Red Hat Linux分区。
·使用 Disk Druid 来手工分区 - 不要删除现存 Windows 分区(它们是类型为 vfat 的分区)。在附加硬盘驱动器上,或你为 Red Hat Linux保留的空闲空间上创建 Linux 分区。
·使用 fdisk 来手工分区 - 与使用 Disk Druid 相似,只是你将看不到图形化界面。基本步骤是相同的。不要删除类型为 FAT16、 FAT32、或 NTFS 的现存分区。在附加硬盘驱动器上,或你为 Red Hat Linux 保留的空闲空间上创建 Linux 分区。
配置引导装载程序当你在 Red Hat Linux 安装中运行到了 「安装引导装载程序」 这一屏幕时,选择要安装的引导装载程序。你可以使用不同的引导装载程序来引导 Red Hat Linux 和 Windows。 Red Hat 不支持其它引导装载程序,因此,本章节将只讨论如何配置 GRUB 或 LILO 来引导这两个操作系统。
Red Hat Linux 安装程序通常会检测到 Windows 并自动配置引导装载程序(GRUB 或 LILO)来引导 Red Hat Linux 或 Windows。这可以在安装程序中的引导装载程序屏幕中看到。 一个名为「DOS」的项目会出现在要引导的操作系统列表中。
安装后安装之后,无论你在什么时候启动计算机,你都能够在引导装载程序屏幕中指明你想启动的是Red Hat Linux还是另外的操作系统。 选择「Red Hat Linux」来引导 Red Hat Linux,选择「DOS」来引导 Windows。
如果你没有把硬盘驱动器中全部空闲空间拨给Red Hat Linux,你可以在安装Red Hat Linux之后把它拨给Windows。最好使用fdisk来创建这些分区。其它分区软件会改变硬盘驱动器上的分区表,并移动Linux分区。
但是有时候为了方便而需要使用NT loader 来引导linux,下面就是实现的方法。
你应该牢牢记住的最重要的一点是,许多软件产品会利用硬盘上面仅有的那个宝贵的主引导记录MBR。NT是这样,没有选择余地;Linux也可以这样,如果你喜欢。机器的BIOS会执行储存在当前激活分区的信息,来初始化你希望的操作系统。
NT安装后,MBR会被修改成去引导一个在激活分区的根目录下,叫NTLDR的程序。原来的MBR会被存到一个叫BOOTSECT.DOS的小文件中。NT安装完成后要记住绝不能覆盖这个MBR, 否则NT将无法启动。以防万一, NT的用户需要NT的应急修复磁盘(Emergency Repair Disk,ERD)。
记住了这些后,就要注意设定LILO时***不能***装到MBR中去,而是装到Linux的root分区中去。这样,对NT而言,不会带来问题;而Linux没有MBR也可以活下去。
NT的引导过程
当NTLDR启动, NT用户看到"OS Loader V4.xx" 后,它会切换处理器到386状态,并启动一个非常小的文件系统。接着,它会去读BOOT.INI文件,看是否有其它操作系统存在,并显示一个选择菜单。下面是一个典型的BOOT.INI:
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(2)WINNT
[operating systems]
multi(0)disk(0)rdisk(0)partition(2)WINNT="NT V4 is here"
multi(0)disk(0)rdisk(0)partition(2)WINNT="NT V4 VGAMODE" /basevideo /sos
C:="DOS is here"
BOOT.INI有两部分构成。 "boot loader section"部分指定菜单在屏幕上的停留时间,和缺省菜单选项。"opearating systems section" 部分指定可选的操作系统种类。可以看到机器可以启动NT(以标准模式或VGA安全模式)和DOS。从这个例子我们可以推断,DOS从硬盘C:(第一个硬盘的第一个分区)启动,而NT从第二个分区启动。典型安装时,会以DOS的FAT文件系统格式化一个C:的分区,然后将NT装在另外一个NTFS(NT文件系统)的分区。
如果用户选择了启动NT, 另外一个程序NTDETECT.COM,就会开始进行硬件检查。如果一切正常,NT内核就会被装入,正如我们都知道的那样。
再来看如果启动的不是NT的情形。此时,NTLDR 需要知道非NT OS引导所必需的引导扇区是哪个。此时,相应的引导扇区映象必须要在一个小小的512字节的文件中。比如,要引导DOS,NTLDR 将会寻找一个叫BOOTSECT.DOS的引导扇区映象文件。 这个映象文件是NT的安装程序产生的。
那么, 引导Linux又是怎样呢?这很简单,需要的只是一个引导扇区映象文件,姑且称之为BOOTSECT.LIN (在本文稍后会看到如何得到这个文件)。 必须将BOOTSECT.LIN 放到C:, 并要修改 BOOT.INI。此时"operating systems ection"部分看起来应该是这样的:
[operating systems]
multi(0)disk(0)rdisk(0)partition(2)WINNT="NT V4 is here"
multi(0)disk(0)rdisk(0)partition(2)WINNT="NT V4 VGAMODE" /basevideo /sos
C:="DOS is here"
C:BOOTSECT.LIN="Now Linux is here"
修改BOOT.INI, 可以用任何普通ASCII文本编辑器(比如记事本)。这个文件的正常属性为系统-隐藏-只读,所以你必须用 'attrib' DOS 命令或在NT中,用文件属性对话框中来变更属性。
现在我们将注意力转到Linux。我们需要安装Linux,定制LILO,产生BOOTSECT.LIN文件。
第一步是装好Linux。我们都知道怎么做:为Linux选适当的系统,SWAP,和用户分区,运行安装程序,等等。一切顺利时,这一步在45分钟之内就可以完成。
接下去就要定制LILO。我们知道怎么做,但要注意*不能* 将LILO装到MBR中去(除非你想将NT吞了:-))。设定LILO时,要选择将它装到你Linux 的root分区。如果你还不知道如何设定LILO, 就花几分钟读读HOW-TO文献,或者就用一些好的安装程序,我是用S.u.S.E.的, 因此我的安装程序就是 'yast' (Yet Another Setup Tool)。
LILO定制好之后,(为行文方便, 此处假设Linux的root分区是/dev/hda3)我们必须用'dd'来产生引导记录映象文件。以root Login后,按以下做:
# dd if=/dev/hda3 bs=512 count=1 of=/dosc/bootsect.lin
如果没有能将FAT C: partition mount成为 /dosc,譬如说由于这个分区被以NTFS方式格式化,不能访问这个分区。此时可以将 BOOTSECT.LIN写到一个以DOS方式格式化的磁盘中,或者NT能读的其它什么分区也可以。如果BOOTSECT.LIN不是被放到C:,要记住此时应相应修改BOOT.INI文件。
现在可以从NT Loader菜单中选择Linux了。NTLDR将会装载BOOTSECT.INI,就可以看到LILO的提示。
最后,你可以设定LILO在选择提示时能去引导Linux和C: 上的DOS。就可以再次回到C: 分区上的NT Loader。前文描述的方法可以反复进行,如果你希望能选择引导多个Linux,就必须为每一个Linux都产生一个相应的引导扇区映象文件。