SpongeBob

人生三种境界:昨夜西风凋碧树,独上高楼,望尽天涯路。 衣带渐宽终不悔,为伊消得人憔悴。 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。
扩大
缩小

CentOS6启动流程

        熟悉系统启动流程对我们学习Linux是非常有帮助的。虽然这是很基础的,但能帮助我们更加了解Linux的运行机制。我们在了解了系统启动流程后,系统在启动过程中,发生的问题时候,就知道是什么阶段出现问题,从而“哪痛医哪”,就不需要重装系统了。 
       CentOS6和CentOS启动流程类似,不过CentOS6和7在启动后期不一样,CentOS6后期是init,CentOS7是systemd。下面我们将以CentOS6为例来介绍Linux系统的启动流程。

CentOS6启动流程

 

 

 

1.POST加电自检

        加载BIOS的硬件信息,获取第一个启动设备。自检主要是检测一下硬件设备是否存在并且能正常运行。例如BIOS会检测CPU、内存以及I/O设备是否能够正常运行,如果是个人计算机的话可能还会检测一下显示器。只要一通电,CPU就会自动去加载ROM芯片上的BIOS程序,是这样来实现的。而检测完成之后进行硬件设备的初始化

2.MBR引导加载

       当第一步自检硬件没有问题时候,这里以BIOS为例,BIOS将会直接去找硬盘的第一个扇区,找到前446字节,将MBR加载到内存中,MBR将告诉程序下一阶段去哪里找系统grub引导。这个阶段属于grub的第一阶段。前面的BIOS通过读取并执行启动设备的MBR中的bootloader,而bootloader要实现的功能就是提供一个菜单给用户,让用户去选择要启动的系统或不同的内核版本,因为一块硬盘上可能不止一个操作系统。然后把用户选择的内核版本加载到RAM中的特定空间,接着在RAM中解压、展开,而后把系统控制权移交给内核。

        grub是bootloader中的一种,对于grub来说,为了打破在MBR中只有446Bytes用于存放bootloader这一限制,grub是通过分成三个阶段来实现加载内核这一功能的,这三个阶段分别是:stage1, stage1.5以及stage2。其中:

        stage1:存放于MBR的前446Bytes,用于加载stage1.5阶段,目的是为了判断启动分区的文件系统类型;

        stage1.5:存放于MBR之后的扇区,加载stage2所在分区的文件系统驱动,让stage1中的bootloader能识别stage2所在分区的文件系统;

        stage2:存放于磁盘分区之上,具体存放于/boot/grub目录之下,主要用于加载内核文件以及ramdisk这个临时根文件系统。

        总而言之,假如要启动的是硬盘设备,首先BIOS必须能够识别硬盘,然后BIOS才能加载硬盘中的bootloader,而bootloader自身加载后就能够直接识别当前主机上的硬盘设备了。不过,能够识别硬盘设备不代表能够识别硬盘设备中的文件系统,因为文件系统是额外附加的一层软件组织的文件结构,所以要对接一种文件系统,就必须要有对应的能够识别和理解这种文件系统的驱动,这种驱动就称为文件系统驱动。而stage1.5就是向grub提供文件系统驱动的,这样stage1就能访问stage2及内核所在的分区(/boot)了。

3.加载系统内核kernel,执行系统初始化信息

        在Bootloader开始读取操作系统内核文件时,接下来会将内核文件解压缩后装在到内存当中,然后根据内核提供的功能开始加载各个设备。这里的各个操作都是由内核来完成的,而我们的内核文件通常都存放在/boot目录当中,并且是一个vmlinux开头的文件。如下图所示:

[root@centos6 ~]# cd /boot
[root@centos6 boot]# pwd
/boot
[root@centos6 boot]# ls
config-2.6.32-696.el6.x86_64           lost+found
efi                                    symvers-2.6.32-696.el6.x86_64.gz
grub                                   System.map-2.6.32-696.el6.x86_64
initramfs-2.6.32-696.el6.x86_64.img    vmlinuz-2.6.32-696.el6.x86_64
initrd-2.6.32-696.el6.x86_64kdump.img

       但是,此时内核程序还没有加载到磁盘,如何读取内核文件呢?如果要先加载磁盘,就要有磁盘驱动程序,而驱动程序又在硬盘上,这样就陷入了一个无限循环。所以我们要采用一种叫做虚拟文件系统的东西来解决这个问题。同样的,这个文件系统也放在了/boot下,是一个initrd开头的文件,如上图所示。

        Boot Loader可以加载kernel和initrd,然后把initrd解压成根目录,然后内核就可以在这个虚拟的根文件系统上加载驱动程序,之后释放根文件系统,最后开始正常的启动过程。

4.启动init

        对于CentOS6来说,init配置文件为:/etc/inittab, /etc/init/*.conf,也就是upstart将配置文件拆分成多个,在/etc/init/目录下以conf结尾的都是upstart风格的配置文件,而/etc/inittab仅用于设置默认运行级别。运行级别是为了系统运行或维护等目的而设定,分为0-6,共七个级别:

     0:关机(shutdown);

     1:单用户模式(single user):不需要通过认证,登录进去之后为root用户身份;

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

     3:多用户模式(multi user):为完全功能模式,提供文本界面;

     4:预留级别,目前无特别使用目的;

     5:多用户模式(multi user):为完全功能模式,提供图形化界面;

     6:重启(reboot),reboot;

CentOS6 /etc/inittab配置文件代码如下:

[root@centos6 ~]# cat /etc/inittab 
# inittab is only used by upstart for the default runlevel.
#
# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# System initialization is started by /etc/init/rcS.conf
#
# Individual runlevels are started by /etc/init/rc.conf
#
# Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
#
# Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
# with configuration in /etc/sysconfig/init.
#
# For information on how to write upstart event handlers, or how
# upstart works, see init(5), init(8), and initctl(8).
#
# Default runlevel. The runlevels used are:
#   0 - halt (Do NOT set initdefault to this)
#   1 - Single user mode
#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
#   3 - Full multiuser mode
#   4 - unused
#   5 - X11
#   6 - reboot (Do NOT set initdefault to this)
# 
id:5:initdefault:

        通常我们使用默认级别3或5,不同级别的页面是可以切换的,切换方式为:init[0-6],使用runlevel命令来查看当前运行的级别。

init的处理过程:

       运行初始化脚本是为了初始化系统环境,/etc/rc.d/rc.sysint所做的事情包括:

       (1)设置主机名;

       (2)设置欢迎信息;

       (3)激活udev和selinux;

       (4)挂载/etc/fstab文件中定义的所有文件系统;

       (5)检测根文件系统,以读写方式重新挂载根文件系统;

       (6)设置系统时钟;

       (7)根据/etc/sysctl.conf文件来设置内核参数;

       (8)激活lvm及软raid设备;

       (9)激活swap设备;

       (10)加载额外设备的驱动程序(因为内核只加载根文件系统所在分区的驱动程序);

       (11)清理操作;

       在/etc/rc.d/rc.sysint初始化完成系统之后,系统就要开始启动各项服务,这里通过运行/etc/rc.d/rc这个脚本文件,而初始化程序init根据前面获取的默认运行级别信息,将这个运行级别数字以参数方式传递给/etc/rc.d/rc脚本中的变量$runlevel;然后,这个脚本会以glob方式去把/etc/rc.d/rc$runlevel.d/S*匹配到的脚本所控制的服务开启,而把/etc/rc.d/rc$runlevel.d/K*匹配到的脚本所控制的服务关闭。

/etc/rc.d/rc#.d/目录下的脚本文件命名格式:

     (1)K##*:表示要停止的服务;'##'表示关闭优先级,数字越小,越是优先关闭;依赖到其他服务的服

              务会优先关闭,而被依赖的服务则后关闭;        

     (2)S##*:表示要启动的服务;'##'表示启动优先级,数字越小,越是优先启动;被依赖的服务会优先

              启动,而依赖到其他服务的服务则后启动;

          以下为/etc/rc.d/rc脚本文件代码节选:

for i in /etc/rc$runlevel.d/K* ; do

        # Check if the subsystem is already up.
        subsys=${i#/etc/rc$runlevel.d/K??}
        [ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] || continue
        check_runlevel "$i" || continue

        # Bring the subsystem down.
        [ -n "$UPSTART" ] && initctl emit --quiet stopping JOB=$subsys
        $i stop
        [ -n "$UPSTART" ] && initctl emit --quiet stopped JOB=$subsys
done

# Now run the START scripts.
for i in /etc/rc$runlevel.d/S* ; do

        # Check if the subsystem is already up.
        subsys=${i#/etc/rc$runlevel.d/S??}
        [ -f /var/lock/subsys/$subsys ] && continue
        [ -f /var/lock/subsys/$subsys.init ] && continue
        check_runlevel "$i" || continue

          根据前面获取的运行级别来启动终端,mingetty程序是用于启动终端的,它会调用登录程序login,这样就能显示出登录提示符了,类似mingetty这种用于打开终端的程序还有getty等. 而如果默认运行级别为5,则会打开图形界面。

以下为CentOS 5的/etc/inittab文件中部分代码:在配置文件这里指明打开留个文本终端,分别对应于[Ctrl]+[Alt]+F1至F6;

# Run gettys in standard runlevels
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

5.用户登录

 

posted on 2018-08-25 10:47  青山揽流萤  阅读(486)  评论(0编辑  收藏  举报

导航