Linux启动流程(参考鸟哥私房菜与百度百科)

1.加载BIOS的硬件信息与进行自我测试,并依据设置取得第一个可启动的设备

BIOS是一组固化到计算机主板上一个ROM芯片上的程序,其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。

BIOS中主要存放:

  ● 自诊断程序:通过读取CMOS RAM中的内容识别硬件配置,并对其进行自检和初始化

  ● CMOS设置程序:引导过程中,用特殊热键启动,进行设置后,存入CMOS RAM中;

  ● 系统自举装载程序:在自检成功后将磁盘相对0道0扇区(MBR:主引导扇区)上的引导程序装入内存,让其运行以装入系统;

  ● 主要I/O设备的驱动程序和中断服务。

2.读取并执行第一个启动设备内MBR的Boot Loader(即是grub,spfdisk等程序)

BIOS通过硬件INT 13中断功能读取MBR内boot loader的。

主引导记录MBR:硬盘的0柱面、0磁头、1扇区称为主引导扇区,共512字节

由三个部分组成,

  • 主引导程序(Boot Loader),占446个字节。
  • 硬盘分区表DPT(Disk Partition table),占64个字节,总共分为4个记录,每个记录记录了该分区起始的柱面号与结束的柱面号。4个分区中至多有1个扩展分区。
  • 硬盘有效标志(55AA),magic number,占2个字节,固定为55AA。

磁盘分区表示意图

 

3.依据Boot Loader的设置加载kernel, kernel会开始检测硬件与加载驱动程序

不同的系统需要用自己的boot loader 才能够加载属于自己的操作系统kernel,而系统的 MBR 只有一个,那你怎么会有办法同时在一部主机上面安装 Windows 与 Linux 呢?其实每个文件系统 (filesystem, 或者是 partition) 都会保留一块启动磁区 (boot sector) 提供操作系统安装 boot loader , 而通常操作系统默认都会安装一份 loader 到他根目录所在的文件系统的 bootsector 上。如果我们在一部主机上面安装 Windows 与 Linux 后,该 boot sector, boot loader 与 MBR 的相关性会有点像下图:

boot secotor 与 操作系统的关系

如上图所示,每个操作系统默认是会安装一套 boot loader 到他自己的文件系统中 (就是每个 filesystem 左下角的方框),而在 Linux 系统安装时,你可以选择将 boot loader 安装到 MBR 去,也可以选择不安装。 如果选择安装到 MBR 的话,那理论上你在 MBR 与 boot sector 都会保有一份 boot loader 程序的。 至於 Windows 安装时,他默认会主动的将 MBR 与 boot sector 都装上一份 boot loader!所以啦,你会发现安装多重操作系统时,你的 MBR 常常会被不同的操作系统的 boot loader 所覆盖啦!

Boot Loader功能是:

  • 提供菜单:使用者可以选择不同的启动项目,这也是多重启动的重要功能!
  • 加载核心文件:直接指向可启动的程序区段来开始操作系统;
  • 转交其他 loader:将启动管理功能转交给其他 loader 负责。

 启动管理程序的菜单功能与控制权转交功能示意图

 

当boot loader开始读取kernel文件后,接下来, Linux 就会将kernel解压缩到主内存当中, 并且利用kernel的功能,开始测试与驱动各个周边装置,包括储存装置、CPU、网络卡、声卡等等。

[root@www ~]# ls --format=single-column -F /boot

config-2.6.18-92.el5      <==此版本核心被编译时选择的功能与模块配置档

grub/                     <==就是启动管理程序 grub 相关数据目录

initrd-2.6.18-92.el5.img  <==虚拟文件系统档!

System.map-2.6.18-92.el5  <==核心功能放置到内存位址的对应表

vmlinuz-2.6.18-92.el5     <==就是核心文件啦!最重要者!

  Linux kernel可以动态加载内核模块的(内核模块就放置在 /lib/modules/ 内)。 由于内核模块放置到根目录内 ( /lib 不可以与 / 分别放在不同的分区内), 因此在启动的过程中核心必须要挂载根目录,才能够读取内核模块,加载驱动程序。 而且为了避免修改磁盘内的文件系统,因此启动过程中根目录是以只读的方式来挂载。非必要的功能且可以编译成为内核模块。 因此 U盘, SATA, SCSI... 等磁盘设备的驱动程序通常都是以内核模块的方式存在。 

  思考一种情况,假设你的 linux 是安装在 SATA磁盘上,通过 BIOS 的 INT 13 取得 boot loader 与 kernel 文件来启动,然后 kernel 会开始接管系统并且侦测硬件及尝试挂载根目录来取得额外的驱动程序。问题是,核心根本不认识 SATA 磁盘,需要加载 SATA 磁盘的驱动, 否则根本就无法挂载根目录。但是 SATA 的驱动在 /lib/modules 内,你根本无法挂载根目录又怎么读取到 /lib/modules/ 内的驱动程序?

  虚拟文件系统 (Initial RAM Disk) 一般使用的档名为 /boot/initrd ,能够透过boot loader来加载到内存中, 然后这个文件会被解压缩并且在内存当中模拟成一个根目录, 且模拟的文件系统能够提供一支可运行的程序,该程序能加载启动过程中所最需要的核心模块, 通常这些模块就是 U盘, RAID, LVM, SCSI 等驱动程序 kernel 就能够借此加载适当的驱动程序,最终释放虚拟文件系统,并挂载实际的根目录文件系统, 就能够开始后续的正常启动流程。

BIOS 与 boot loader 及核心加载流程示意图

4. 在硬件驱动成功后,kernel会主动调用init进程,而init会取得run-level信息

  在核心加载完毕、进行完硬件侦测与驱动程序加载后,主机硬件已经准备就绪了 (ready) , 此时kernel会启动第一个进程 /sbin/init。 其最主要的功能就是读取/etc/inittab,准备软件运行的环境,包括系统的主机名称、网络配置、语系处理、文件系统格式及其他服务的启动等。

[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 则是这行决定的!

  首先,这个文件的语法是利用冒号 (:) 将配置分隔成为四个栏位,每个栏位的意义与说明如下:

[配置项目]:[run level]:[init 的动作行为]:[命令项目]

  • 配置项目:最多四个字节,代表 init 的主要工作项目,只是一个简单的代表说明。

  • run level:该项目在哪些 run level 底下进行的意思。如果是 35 则代表 runlevel 3 与 5 都会运行。

  • init 的动作项目:主要可以进行的动作项目意义有:
    inittab 配置值 意义说明
    initdefault 代表默认的 run level 配置值
    sysinit 代表系统初始化的动作项目
    ctrlaltdel 代表 [ctrl]+[alt]+[del] 三个按键是否可以重新启动的配置
    wait 代表后面栏位配置的命令项目必须要运行完毕才能继续底下其他的动作
    respawn 代表后面栏位的命令可以无限制的再生 (重新启动)。举例来说, tty1 的 mingetty 产生的可登陆画面, 在你注销而结束后,系统会再开一个新的可登陆画面等待下一个登陆。
  • 命令项目:亦即应该可以进行的命令,通常是一些 script 

  CentOS 的 init 依据 inittab 配置的处理流程会是:

  • 先取得 runlevel 亦即默认运行等级的相关等级 (以鸟哥的测试机为例,为 5 号);
  • 使用 /etc/rc.d/rc.sysinit 进行系统初始化
  • 由于 runlevel 是 5 ,因此只进行『l5:5:wait:/etc/rc.d/rc 5』,其他行则略过
  • 配置好 [ctrl]+[alt]+[del] 这组的组合键功能
  • 配置不断电系统的 pf, pr 两种机制;
  • 启动 mingetty 的六个终端机 (tty1 ~ tty6)
  • 最终以 /etc/X11/perfdm -nodaemon 启动图形介面啦!

5.init会执行/etc/rc.d/rc.sysinit文件来准备软件执行的操作环境(如网络、时区等)

如果你使用 vim 去查阅过 /etc/rc.d/rc.sysinit 的话,那么可以发现他主要的工作大抵有这几项:取得网络环境与主机类型:

  • 读取网络配置档 /etc/sysconfig/network ,取得主机名称与默认通讯闸 (gateway) 等网络环境。
  • 测试与挂载内存装置 /proc 及 U盘 装置 /sys:
    除挂载内存装置 /proc 之外,还会主动侦测系统上是否具有 usb 的装置, 若有则会主动加载 usb 的驱动程序,并且尝试挂载 usb 的文件系统。
  • 决定是否启动 SELinux :
    我们在第十七章谈到的 SELinux 在此时进行一些检测, 并且检测是否需要帮所有的文件重新编写标准的 SELinux 类型 (auto relabel)。
  • 启动系统的乱数产生器
    乱数产生器可以帮助系统进行一些口令加密演算的功能,在此需要启动两次乱数产生器。
  • 配置终端机 (console) 字形:
  • 配置显示於启动过程中的欢迎画面 (text banner);
  • 配置系统时间 (clock) 与时区配置:需读入 /etc/sysconfig/clock 配置值
  • 周边设备的侦测与 Plug and Play (PnP) 参数的测试:
    根据核心在启动时侦测的结果 (/proc/sys/kernel/modprobe ) 开始进行 ide / scsi / 网络 / 音效 等周边设备的侦测,以及利用以加载的核心模块进行 PnP 装置的参数测试。
  • 使用者自订模块的加载
    使用者可以在 /etc/sysconfig/modules/*.modules 加入自订的模块,则此时会被加载到系统当中
  • 加载核心的相关配置:
    系统会主动去读取 /etc/sysctl.conf 这个文件的配置值,使核心功能成为我们想要的样子。
  • 配置主机名称与初始化电源管理模块 (ACPI)
  • 初始化软件磁盘阵列:主要是透过 /etc/mdadm.conf 来配置好的。
  • 初始化 LVM 的文件系统功能
  • 以 fsck 检验磁碟文件系统:会进行 filesystem check
  • 进行磁碟配额 quota 的转换 (非必要):
  • 重新以可读写模式挂载系统磁碟:
  • 启动 quota 功能:所以我们不需要自订 quotaon 的动作
  • 启动系统虚拟乱数产生器 (pseudo-random):
  • 清除启动过程当中的缓存文件:
  • 将启动相关资讯加载 /var/log/dmesg 文件中。

6.init执行run-level的各个服务的启动(script方式)

启动系统服务与相关启动配置档 (/etc/rc.d/rc N & /etc/sysconfig)。依据我们在 /etc/inittab 里面提到的 run level 配置值,就可以来决定启动的服务项目了。使用默认的 runlevel 5,即/etc/rc.d/rc 5 的意义是这样的 :

  • 透过外部第一号参数 ($1) 来取得想要运行的脚本目录。亦即由 /etc/rc.d/rc 5 可以取得 /etc/rc5.d/ 这个目录来准备处理相关的脚本程序;
  • 找到 /etc/rc5.d/K??* 开头的文件,并进行『 /etc/rc5.d/K??* stop 』的动作;
  • 找到 /etc/rc5.d/S??* 开头的文件,并进行『 /etc/rc5.d/S??* start 』的动作;

透过上面的说明我们可以知道所有的项目都与 /etc/rc5.d/ 有关,那么我们就来瞧瞧这个目录下有些什么玩意儿吧!

[root@www ~]# ll /etc/rc5.d/

lrwxrwxrwx 1 root root 16 Sep  4  2008 K02dhcdbd -> ../init.d/dhcdbd

....(中间省略)....

lrwxrwxrwx 1 root root 14 Sep  4  2008 K91capi -> ../init.d/capi

lrwxrwxrwx 1 root root 23 Sep  4  2008 S00microcode_ctl -> ../init.d/microcode_ctl

lrwxrwxrwx 1 root root 22 Sep  4  2008 S02lvm2-monitor -> ../init.d/lvm2-monitor

....(中间省略)....

lrwxrwxrwx 1 root root 17 Sep  4  2008 S10network -> ../init.d/network

....(中间省略)....

lrwxrwxrwx 1 root root 11 Sep  4  2008 S99local -> ../rc.local

lrwxrwxrwx 1 root root 16 Sep  4  2008 S99smartd -> ../init.d/smartd

....(底下省略)....

在这个目录下的文件很有趣,主要具有几个特点:

  • 全部是连结档,连结到 stand alone 服务启动的目录 /etc/init.d/ 去
  • 档名全部以 Sxx 或 Kxx ,其中 xx 为数字,且这些数字在文件之间是有相关性的

7.init执行/etc/rc.d/rc.local文件

8.init执行终端机模拟程序mingetty来启动login进程,最后等待用户登录

在完成了系统所有服务的启动后,接下来 Linux 就会启动终端机或者是 X Window 来等待使用者登陆啦! 实际参考的项目是 /etc/inittab 内的这一段:

1:2345:respawn:/sbin/mingetty tty1

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

 

要注意的是那个 respawn 的 init 动作项目,代表『当后面的命令被终止 (terminal) 时, init 会主动的重新启动该项目。』这也是为何我们登陆 tty1 终端机介面后,以 exit 离开后, 系统还是会重新显示等待使用者输入的画面的原因!至於如果我们使用的是 run level 5 呢?那么除了这六个终端机之外, init 还会运行 /etc/X11/prefdm -nodaemon 那个命令,启动X Windows。这一段代表,在 run level 2, 3, 4, 5 时,都会运行 /sbin/mingetty ,而且运行六个,这也是为何我们 Linux 会提供『六个纯文字终端机』的配置所在!

你可能感兴趣的:(linux)