对于计算机来说,不同的操作系统的开机流程大体相似。linux系统中,centos是使用比较广泛的一种,今天我们就主要以centos6为例进行开机流程的简单说明。


先简要介绍完整的开机流程,下面会详细解说:

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

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

            3.依据boot loader的设置加载kernel(内核),kernel会开始检测硬件与加载驱动程序(可能依赖ramdisk虚拟文件系统)

            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进程,最后就等待用户登录

1.POST加电自检

       POST:Power On and SelfTesting,加电后自我检测


       通电以后,主机会自动加载BIOS,并通过BIOS去加载CMOS的信息,取得主机硬件的各个参数,然后BIOS进行开机自检,定义出可启动的设备顺序,就开始进行启动设备的读取了(MBR的任务)

         CMOS:记录各项硬件参数并嵌入在主板上的存储器,只能读取

         BIOS:写入到主板上的一个软件程序,开机时,主机主动执行的第一个程序

         CMOS与BIOS都是写入到主板上的特殊的存储器里面,并不在主机内存中。


2.Boot loader:引导加载器


        Boot loader安装在启动设备的第一个扇区(sector)中,也就是我们一直提到的MBR(Master Boot Record,主引导分区)。对于不同的操作系统,BIOS通过硬件的INT 13中断功能来读取MBR,而INT13是一种硬件中断,是硬件厂商直接设定好的,所以能够做到对于不同的操作系统,BIOS都能正常读取。

        MBR大小为512bytes,其中只有446bytes是bootloader,非常小,对于早期的系统来说,还可以,但对于现在系统来说就有些吃力了。所以对于不同的操作系统来说,设置了多重引导,来增强bootloader的功能。 以centos6为例,它的引导的第一个阶段是在MBR上面,第二阶段就是在磁盘空间上,使得空间大大增加

       对于不同的操作系统,使用了不同的bootloader:

             Windows:ntloader

             Linux:

                LILO:LIinux  LOader(早期使用)

                GRUB:Grand Uniform Bootloader(现在使用)

                     GRUB 0.X:Grub Legacy

                     GRUB 1.X:Grub

这样的多重引导使得bootloader的功能也非常强大。


      bootloader的功能:   

      1.提供一个菜单,允许用户选择要启动的系统或不同的内核版本,在这里可以对内核、开机项进行设置

      2.把用户选定的内核装载到RAM中的特定空间中,解压、展开,

      3.把系统控制权移交给内核;


       在一台主机上同时安装Windows与linux操作系统的说明:

       每个操作系统默认会安装一套bootloader到自己的文件系统中,在linux系统中,你可以选择将bootloader安装到MBR去,也可以选择不安装。如果选择安装到MBR,那理论上你在MBR与bootsector都会保留一份bootloader程序。至于Windows安装时,会默认主动将MBR与bootloader都安装上一份bootloader。所以,在安装多重操作系统时,你的MBR经常会被不同的操作系统的bootloader覆盖。所以,在安装Windows与linux双系统时,一般要先安装Windows,在安装linux。


3.加载Kernel(内核)


    引导完成之后,就要加载指定的内核了,Kernel开始自身的初始化:

           1.探测可识别到的所有硬件设备:此时的检测是linux内核以自己的功能重新检测一次硬件,而不一定会使用BIOS检测到的硬件信息。也就是说,内核此时才开始接管BIOS后的工作。硬件检测进行了两次。    

           2.加载硬件驱动程序;(有可能会借助于ramdisk加载驱动)

           3.以只读方式挂载根文件系统;(以防影响到磁盘内的文件系统,只读模式运行)

           4.切换根文件系统,虚拟根文件系统(ramdisk)与磁盘上的根文件系统“/”切换

           5.运行用户空间的第一个应用程序:/sbin/init

   对于不同版本的操作系统,init程序的类型也不太相同:

                    CentOS 5:SysV init

                        配置文件:/etc/inittab 

                    CentOS 6:Upstart

                        配置文件:/etc/inittab

                            /etc/init/*.conf

                    CentOS 7:Systemd

                        配置文件:/usr/lib/systemd/system/, /etc/systemd/system/


ramdisk:虚拟文件系统

    由于内核根本不认识SATA盘,所以需要加载SATA盘的驱动程序,否则根本无法挂载根目录。但是SATA的驱动又在/lib/modules/内,无法加载根目录,就读取不到/lib/modules/内的驱动程序。所以要使用虚拟文件系统-initialRAM DISK,一般在/lib/initrd中。通过bootloader加载到内存中,然后会被解压到内存中,仿真成一个根文件系统,通过它来加载启动过程中所需要的内核模块。等载入完成后,会帮助内核重新调用/sbin/init来开始后续的正常启动流程。编译好的ramdisk一般会与内核放置在一起,在/boot目录下,加载kernel的同时也会加载ramdisk。

    在/boot目录下的以initramfs开头的文件即是编译好的ramdisk,我们解压一下看看有什么东西

Linux系统启动流程简介_linux

解压后的initramfs-2.6.32-573.el6.x86_64.img,可以看出,其中的文件与一个根文件系统基本类似

Linux系统启动流程简介_linux_02

4.执行第一个初始化程序:/sbin/init

       init的作用:准备软件执行的环境,包括系统的主机名、网络配置、语系处理、文件系统的格式及其他服务的启动等,以上所有的操作都会通过init的配置文件来进行规划,而且,其中还设置了默认的run level(启动执行等级)。

      init的简单处理流程:

       1.先在配置文件/etc/inittab中取得runlevel即默认执行等级的相关等级(以runlevel=5为例)

       2.使用/etc/rc.d/rc.sysinit进行系统初始化

       3.由于系统是5级,所以只执行相关的服务,在/etc/rc.d/rc5.d/sysinit中

       4.启动mingetty的6个终端机(tty1-tty6)

       5.启动开机界面


第一步:执行配置文件,/etc/inittab

Linux系统启动流程简介_开机启动_03

在Centos6系统中,在安装的时候就选定了开机方式,所以只显示一行,在Centos5与之前的版本中显示的是多行,不过也只会执行一行。下面介绍配置文件的内容:

       每行定义一种action以及与之对应的process

                 格式:id:runlevels:action:process 

                       id:一个任务的标识符;

                       runlevels:在哪些级别启动此任务;#,###,也可以为空,表示所有级别;

                       action:在什么条件下启动此任务;

                       process:任务;

                 action:

                      wait:等待切换至此任务所在的级别时执行一次;

                      respawn:一旦此任务终止,就自动重新启动之;

                      initdefault:设定默认运行级别;此时,process省略;

                      sysinit:设定系统初始化方式,此处一般为指定/etc/rc.d/rc.sysinit脚本;

                 例如:

                      id:3:initdefault: 

                      id:5:initdefault:

                      si::sysinit:/etc/rc.d/rc.sysinit

                      l0:0:wait:/etc/rc.d/rc  0

                      l1:1:wait:/etc/rc.d/rc  1

                            …………

                      l6:6:wait:/etc/rc.d/rc  6


        系统的运行级别:为了系统的运行或维护等目的而设定的机制,共有0-6,7个级别;

               0:关机, shutdown

               1:单用户模式(single user),root用户,无须认证;维护模式;

               2、多用户模式(multi user),会启动网络功能,但不会启动NFS;维护模式;

               3、多用户模式(mutli user),完全功能模式;文本界面;

               4、预留级别:目前无特别使用目的,但习惯以同3级别功能使用;

               5、多用户模式(multi user), 完全功能模式,图形界面;

               6、重启,reboot

                    默认级别:3, 5

                    级别切换:init #

                    级别查看:

                        who -r

                        runlevel 


二步:选定要执行的运行级别,就开始使用/etc/rc.d/rc.sysinit进行系统初始化


              1.取得网络环境与主机类型

              2.测试与挂载内存设备/proc以及USB设备/sys

              3.决定是否启动SElinux

              4.启动系统的随机数生成器,进行一些密码加密演算的功能

              5.设置终端字体

              6.设置显示于启动过程中的欢迎界面

              7.设置系统时间(clock)与时区设置:需读入/etc/sysconfig/clock设置

              8.接口设备的检测与PnP参数的测试

              9.用户自定义模块的加载,在/etc/sysconfig/modules/*.modules中加入的自定义模块,在此刻被加载到系统中

             10.加载内核的相关设置,读取/etc/sysctl.conf这个文件的设置,使内核成为我们想要的样子

             11.设置主机名与初始化电源管理模块(ACPI)

             12.初始化磁盘阵列

             13.初始化LVM的文件系统功能

             14.以fsck检测磁盘文件系统:会进行filesystem check

             15.重新以可读写模式挂载系统磁盘

             16.启动系统伪随机数生成器

             17.清除启动过程中的临时文件

             18.将启动信息加载到/var/log/dmesg文件中

对整个开机流程比较感兴趣的可以查找/var/log/dmesg文件,查找更详细的过


第三步:启动或关闭/etc/rc.d/rc5.d/目录下的服务脚本所控制服务

我们打开/etc/rc.d/rc5.d目录,可以看到:

Linux系统启动流程简介_流程_04

 K*:要停止的服务;K##*,优先级,数字越小,越是优先关闭;依赖的服务先关闭,而后关闭被依赖的;

 S*:要启动的服务;S##*,优先级,数字越小,越是优先启动;被依赖的服务先启动,而依赖的服务后启动;

/etc/rc.d/rc#(0-6).d/之下的文件基本上就是链接文件,指向在/etc/init.d/*目录下具体的执行程序

Linux系统启动流程简介_linux_05

我们还可以通过chkconfig命令,管控/etc/init.d/每个服务脚本在各级别下的启动或关闭状态;

       用法:

            查看:chkconfig  --list   [name]

            添加:chkconfig  --add 

            删除:chkconfig  --del  name

            修改指定的链接类型:

                  chkconfig  [--level  LEVELS]  name  <on|off|reset>

                              --level LEVELS:指定要控制的级别;默认为2345;

Linux系统启动流程简介_开机启动_06

    注意:正常级别下,最后启动的一个服务S99local没有链接至/etc/init.d下的某脚本,而是链接至了/etc/rc.d/rc.local(/etc/rc.local)脚本;因此,不便或不需写为服务脚本的程序期望能开机自动运行时,直接放置于此脚本文件中即可。


第四步:mingetty会调用login程序,打开虚拟终端

        注意:打开虚拟终端的程序除了mingetty之外,还有诸如getty等;


第五步.打开设定的开机界面(3,为命令行界面。5,为图形化界面)

       总结(用户空间的启动流程): /sbin/init (/etc/inittab) 

       设置默认运行级别 --> 运行系统初始化脚本,完成系统初始化 --> 关闭对应级别下需要停止的服务,启动对应级别下需要开启的服务--> 设置登录终端 [--> 启动终端]


      CentOS系统的启动流程就介绍到这里,对于其中的一些内容比如开机引导grub,kernel等没有进行详细介绍,留待下一次进行介绍了。

       对于计算机而言,整个开机流程,从硬件到软件,对于Linux、Windows这些操作系统,基本流程都是大体相似的。通过对于开机配置文件的修改,就可以设置我们自己的操作系统了。