简单来说,系统启动的经过可以汇整成底下的流程的:
1.加载 BIOS 的硬件资讯与进行自我测试,并依据配置取得第一个可启动的装置;
2.读取并运行第一个启动装置内 MBR 的 boot Loader (亦即是 grub, spfdisk 等程序);
3.依据 boot loader 的配置加载 Kernel ,Kernel 会开始侦测硬件与加载驱动程序;
4.在硬件驱动成功后,Kernel 会主动呼叫 init 程序,而 init 会取得 run-level 资讯;
5.init 运行 /etc/rc.d/rc.sysinit 文件来准备软件运行的作业环境 (如网络、时区等);
6.init 运行 run-level 的各个服务之启动 (script 方式);
7.init 运行 /etc/rc.d/rc.local 文件;
8.init 运行终端机模拟程序 mingetty 来启动 login 程序,最后就等待使用者登陆咯;
在个人计算机架构下,你想要启动整部系统首先就得要让系统去加载 BIOS (Basic Input Output System),并透过 BIOS 程序去加载 CMOS 的资讯,并且藉由 CMOS 内的配置值取得主机的各项硬件配置。
BIOS 会指定启动的装置好让我们可以读取磁碟中的操作系统核心文件。 但由於不同的操作系统他的文件系统格式不相同,因此我们必须要以一个启动管理程序来处理核心文件加载 (load) 的问题, 因此这个启动管理程序就被称为 Boot Loader 了。那这个 Boot Loader 程序安装在哪里呢?就在启动装置的第一个磁区 (sector) 内,也就是我们一直谈到的 MBR (Master Boot Record, 主要启动记录区)。
Loader 的最主要功能是要认识操作系统的文件格式并据以加载核心到主内存中去运行。 由於不同操作系统的文件格式不一致,因此每种操作系统都有自己的 boot loader。
问题:系统的MBR只有一个,那你怎么会有办法同时在一部主机上面安装 Windows 与 Linux 呢?
其实每个文件系统 (filesystem, 或者是 partition) 都会保留一块启动磁区 (boot sector) 提供操作系统安装 boot loader , 而通常操作系统默认都会安装一份 loader 到他根目录所在的文件系统的 boot sector 上。
在 Linux 系统安装时,你可以选择将 boot loader 安装到 MBR 去,也可以选择不安装。 如果选择安装到 MBR 的话,那理论上你在 MBR 与 boot sector 都会保有一份 boot loader 程序的。 至於 Windows 安装时,他默认会主动的将 MBR 与 boot sector 都装上一份 boot loader。
提供菜单:使用者可以选择不同的启动项目,这也是多重启动的重要功能;
加载核心文件:直接指向可启动的程序区段来开始操作系统;
转交其他 loader:将启动管理功能转交给其他 loader 负责。(Windows 的 loader 默认不具有控制权转交的功能!所以要先装 Windows 再装 Linux~ )
现在我电脑装了双系统,那么启动程序是怎样的呢?
我的 MBR 使用 Linux 的 grub 这个启动管理程序,并且里面假设已经有了三个菜单, 第一个菜单可以直接指向 Linux 的核心文件并且直接加载核心来启动;第二个菜单可以将启动管理程序控制权交给 Windows 来管理,此时 Windows 的 loader 会接管启动流程,这个时候他就能够启动 windows 了。第三个菜单则是使用 Linux 在 boot sector 内的启动管理程序,此时就会跳出另一个 grub 的菜单~
选择之后,booter就开始加载核心文件~
boot loader 开始读取核心文件后,Linux 就会将核心解压缩到主内存当中, 并且利用核心的功能,开始测试与驱动各个周边装置,包括储存装置、CPU、网络卡、声卡等等。 此时 Linux 核心会以自己的功能重新侦测一次硬件,而不一定会使用 BIOS 侦测到的硬件资讯!也就是说,核心此时开始接管 BIOS 的工作了。 那么核心文件在哪里?一般来说,他会被放置到 /boot 里面,并且取名为 /boot/vmlinuz 。
虚拟文件系统 (Initial RAM Disk) 一般使用的档名为 /boot/initrd ,这个文件的特色是,他也能够透过 boot loader 来加载到内存中, 然后这个文件会被解压缩并且在内存当中模拟成一个根目录, 且此模拟在内存当中的文件系统能够提供一支可运行的程序,透过该程序来加载启动过程中所最需要的核心模块, 通常这些模块就是 U盘, RAID, LVM, SCSI 等文件系统与磁碟介面的驱动程序!等加载完成后, 会帮助核心重新呼叫 /sbin/init 来开始后续的正常启动流程。
(用于加载挂载目录所需的驱动模块~因为挂载需要一些驱动,而驱动在文件系统中,挂载之前无法读取!)
/sbin/init 最主要的功能就是准备软件运行的环境,包括系统的主机名称、网络配置、语系处理、文件系统格式及其他服务的启动等。 而所有的动作都会透过 init 的配置档,亦即是 /etc/inittab 来规划,而 inittab 内还有一个很重要的配置项目,那就是默认的 runlevel (启动运行等级) 。
0 - halt (系统直接关机)
1 - single user mode (单人维护模式,用在系统出问题时的维护)
2 - Multi-user, without NFS (类似底下的 runlevel 3,但无 NFS 服务)
3 - Full multi-user mode (完整含有网络功能的纯文字模式)
4 - unused (系统保留功能)
5 - X11 (与 runlevel 3 类似,但加载使用 X Window)
6 - reboot (重新启动)
[root@www ~]# vim /etc/inittab
id:5:initdefault: <==默认的 runlevel 配置, 此 runlevel 为 5
si::sysinit:/etc/rc.d/rc.sysinit <==准备系统软件运行的环境的脚本运行档
# 7 个不同 run level 的,需要启动的服务的 scripts 放置路径:
l0:0:wait:/etc/rc.d/rc 0 <==runlevel 0 在 /etc/rc.d/rc0.d/
l1:1:wait:/etc/rc.d/rc 1 <==runlevel 1 在 /etc/rc.d/rc1.d/
l2:2:wait:/etc/rc.d/rc 2 <==runlevel 2 在 /etc/rc.d/rc2.d/
l3:3:wait:/etc/rc.d/rc 3 <==runlevel 3 在 /etc/rc.d/rc3.d/
l4:4:wait:/etc/rc.d/rc 4 <==runlevel 4 在 /etc/rc.d/rc4.d/
l5:5:wait:/etc/rc.d/rc 5 <==runlevel 5 在 /etc/rc.d/rc5.d/
l6:6:wait:/etc/rc.d/rc 6 <==runlevel 6 在 /etc/rc.d/rc6.d/
# 是否允许按下 [ctrl]+[alt]+[del] 就重新启动的配置项目:
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
# 底下两个配置则是关於不断电系统的 (UPS),一个是没电力时的关机,一个是复电的处理
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
1:2345:respawn:/sbin/mingetty tty1 <==其实 tty1~tty6 是由底下这六行决定的。
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
x:5:respawn:/etc/X11/prefdm -nodaemon <==X window 则是这行决定的!
CentOS 的 init 依据 inittab 配置的处理流程会是:
1.先取得 runlevel 亦即默认运行等级的相关等级 (假设为 5 号);
2.使用 /etc/rc.d/rc.sysinit 进行系统初始化;
3.由於 runlevel 是 5 ,因此只进行『l5:5:wait:/etc/rc.d/rc 5』,其他行则略过;
4.配置好 [ctrl]+[alt]+[del] 这组的组合键功能;
5.配置不断电系统的 pf, pr 两种机制;
6.启动 mingetty 的六个终端机 (tty1 ~ tty6);
7.最终以 /etc/X11/perfdm -nodaemon 启动图形介面.
/etc/inittab 里头有这一句『 si::sysinit:/etc/rc.d/rc.sysinit 』,这表示:『我开始加载各项系统服务之前,得先做好整个系统环境,我主要利用 /etc/rc.d/rc.sysinit 这个 shell script 来配置好我的系统环境。』
如果你使用 vim 去查阅过 /etc/rc.d/rc.sysinit 的话,那么可以发现他主要的工作大抵有这几项:
1.取得网络环境与主机类型:
读取网络配置档 /etc/sysconfig/network ,取得主机名称与默认通讯闸 (gateway) 等网络环境。
2.测试与挂载内存装置 /proc 及 U盘 装置 /sys:
除挂载内存装置 /proc 之外,还会主动侦测系统上是否具有 usb 的装置, 若有则会主动加载 usb 的驱动程序,并且尝试挂载 usb 的文件系统。
3.决定是否启动 SELinux :
SELinux 在此时进行一些检测, 并且检测是否需要帮所有的文件重新编写标准的 SELinux 类型 (auto relabel)。
4.启动系统的乱数产生器
乱数产生器可以帮助系统进行一些口令加密演算的功能,在此需要启动两次乱数产生器。
5.配置终端机 (console) 字形:
6.配置显示於启动过程中的欢迎画面 (text banner);
7.配置系统时间 (clock) 与时区配置:需读入 /etc/sysconfig/clock 配置值;
8.周边设备的侦测与 Plug and Play (PnP) 参数的测试:
根据核心在启动时侦测的结果 (/proc/sys/kernel/modprobe ) 开始进行 ide / scsi / 网络 / 音效 等周边设备的侦测,以及利用以加载的核心模块进行 PnP 装置的参数测试;
9.使用者自订模块的加载
使用者可以在 /etc/sysconfig/modules/*.modules 加入自订的模块,则此时会被加载到系统当中;
10.加载核心的相关配置:
系统会主动去读取 /etc/sysctl.conf 这个文件的配置值,使核心功能成为我们想要的样子;
11.配置主机名称与初始化电源管理模块 (ACPI);
12.初始化软件磁盘阵列:主要是透过 /etc/mdadm.conf 来配置好的;
13.初始化 LVM 的文件系统功能;
14.以 fsck 检验磁碟文件系统:会进行 filesystem check;
15.进行磁碟配额 quota 的转换 (非必要);
16.重新以可读写模式挂载系统磁碟;
17.启动 quota 功能:所以我们不需要自订 quotaon 的动作;
18.启动系统虚拟乱数产生器 (pseudo-random);
19.清除启动过程当中的缓存文件;
20.将启动相关资讯加载 /var/log/dmesg 文件中。
/etc/inittab 里面提到:
l5:5:wait:/etc/rc.d/rc 5
/etc/rc.d/rc 5 的意义是这样的:
1.透过外部第一号参数 ($1) 来取得想要运行的脚本目录。亦即由 /etc/rc.d/rc 5 可以取得 /etc/rc5.d/ 这个目录来准备处理相关的脚本程序;
2.找到 /etc/rc5.d/K??* 开头的文件,并进行『 /etc/rc5.d/K??* stop 』的动作;
3.找到 /etc/rc5.d/S??* 开头的文件,并进行『 /etc/rc5.d/S??* start 』的动作;
实际上,/etc/rc5.d/[SK]xx 其实就是跑到 /etc/init.d/ 去找到相对应的服务脚本, 然后分别进行 start (Sxx) 或 stop (Kxx) 的动作而已。
我们有任何想要在启动时就进行的工作时,直接将他写入 /etc/rc.d/rc.local , 那么该工作就会在启动的时候自动被加载。
启动过程会用到的配置档则大多放置在 /etc/sysconfig/ 目录下。 同时,由於核心还是需要加载一些驱动程序 (核心模块),此时系统自订的装置与模块对应档 (/etc/modprobe.conf) 就显的挺重要了。
1.如果要每次启动都运行某个默认的 run level ,则需要修改 /etc/inittab 内的配置项目, 亦即是『 id:5:initdefault: 』里头的数字;
2.如果仅只是暂时变更系统的 run level 时,则使用 init [0-6] 来进行 run level 的变更。 但下次重新启动时,依旧会是以 /etc/inittab 的配置为准。
**利用『 init 0 』就能够关机, 而『 init 6 』就能够重新启动!