一、linux系统的启动流程
       关于linux系统的启动流程我们可以按步进行划分为如下几个步骤:

POST加电自检-->BIOS(Boot Sequence)-->加载对应引导上的MBR(bootloader)-->主引导设置加载其 BootLoader-->Kernel初始化-->initrd-->/etc/init进程加载/etc/inittab,其进程流程图如下:

wKioL1MWuLLCVplCAAd0IFe6_a4975.jpg

(图1)


二、剖析详细启动过程

(1)POST开机自检

       电脑主机打开电源的时候,随后会听到滴的一声,系统启动开始了开机自检(POST-power on selftest)自检开始),这个过程中主要是检测计算机硬件设备比如:CPU,内存,主板,显卡,CMOS等设备是否有故障存在,如果有硬件故障的话将按两种情况理:对于严重故障(致命性故障)则停机,此时由于各种初始化操作还没完成,不能给出任何提示或信号;对于非严重故障则给出提示或声音报警信号,等待用户处理),如果没有故障,POST完整自己的接力任务,将尾部工作交接给BIOS处理。

wKioL1MWtWbyi6CjAADl2s9RRE0065.jpg

(图2)


(2)BIOS

       计算机加电自检完成后第一个读取的地方就是就是BIOS(Basic Input Output System,基础输入输出系统),BIOS里面记录了主机板的芯片集与相关设置,如CPU与接口设备的通信频率、启动设备的搜索顺序、硬盘的大小与类型、系统时间、外部总线、各种接口设备的I/O地址、已经与CPU通信的IRQ中断信息,所以,启动如果要顺利启动,首先要读取BIOS设置。但是如果BIOS找不到任何的引导设备那么启动将会失败.

wKioL1MWtbCA9umwAAFBhXMC-Fs581.jpg

(图3)

(3)按照BIOS所设定的系统启动流程,如果检测通过,则根据引导次序(Boot Sequence)开始在第一台设备上支持启动程序,我们的启动设备主要包括硬盘、USB、SD等,我们一般用的是硬盘,然后进行读取第一个设备就是硬盘,第一个要读去的就是该硬盘的主引导记录MBR(Master Boot Record),然后系统可以根据启动区安装的引导加载程序(Boot Loader)开始执行核心识别的工作。【MBR一共是512字节,其中446字节是加载内核文件由它确定选择的操作系统内核】

(4)Boot Loader 加载Grub程序

wKiom1MWthuwc1HCAABAThfaUhI227.jpg

(图4)

在这个过程中主要靠Grub的引导开始的,Grub分为3个阶段:

stage1:主要是Boot loader,位于MBR中,它的存在是为了引导stage2

stage 1.5:位于boot分区(基本磁盘分区),为识别内核文件系统提供文件系统识别扩展

stage2:也是位于boot分区(基本磁盘分区),Grub的引导程序

wKioL1MWuUihyBX_AAFU_TA9Syw454.jpg

(图5)

在/boot/grub/下面我们看到了熟悉的stage1,stage2及grub工具的配置文件grub.conf,那么grub.conf内都定义了什么呢?

首先我们先了解一下grub的功能有哪些:
Grub的功能

选择要启动的内核或系统;

如果系统有多个内核并存时我们可以通过在系统启动倒计时时我们按任意键进入选择需要用的内核或系统,但是我的系统只有一个操作系统,所以它默认时间一到就进入当前的系统了

wKiom1MWzQuQ9rlSAABI4DX9Az8920.jpg

(图6)

wKiom1MWuiSzwPY-AAEXyJZ6J3c082.jpg

(图7)

当系统启动到此时时我们可以输入e键盘进入交互式界面

wKioL1MWuf6Q5vWyAAAei4lbYkg893.jpg

(图8)

交互式接口

   如图7所示我们就可以按照上面的一些说明进入交互式模式了
◆基于密码保护(此知识点将作为另一个单独一个分支总结,再次就不再赘述)


在了解了grub的功能后我们再来看一下grub.conf的配置文件都配置了些什么.如下

[root@Gmq grub]# vim grub.conf
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after makingchanges to this file
# NOTICE:You havea /boot partition.This means that
#allkernel and initrd paths are relative to /boot/, eg.
#root(hd0,0)
#kernel/vmlinuz-version ro root=/dev/mapper/vg0-root
#initrd/initrd-[generic-]version.img
#boot=/dev/sda
default=0 #→操作系统或内核的标题
timeout=5 #→选择内核文件超时时间
splashimage=(hd0,0)/grub/splash.xpm.gzgrub #→界面下的系统启动背景图片
hiddenmenu #→菜单隐藏
title CentOS (2.6.32-431.el6.x86_64)  #→grub标题
root(hd0,0) #→设定内核文件所在的分区为grub的根
kernel/vmlinuz-2.6.32-431.el6.x86_64 ro root=/dev/mapper/vg0-root rhgb quiet #→定义要使用的内核文件,后面可附加传递给内核的启动参数
initrd/initramfs-2.6.32-431.el6.x86_64.img #→指定为内核提供额外驱动等功能的ram disk或ram fs文件


通过该文件我们可以知道了它的配置语法,那有人会问我们为什么要学习他的语法呢,至于为什么 你懂的,不扯了 继续看!

#grub.conf配置文件语法:
default=# #→指定默认启动的内核或OS;
timeout=# #→等待用户选择要启动的内核或OS的时长,单位为秒;
splashimage=/path/to/splashimage_file #→指定使用的背景图片
hiddenmenu #→隐藏菜单
title
    root (hd0,0)(Device, Part) #→Device表示方式: 在grub中,统统以hd开头,并紧跟一个数字做各磁盘设备的标记,从0开始编号 Part表示方式:代表分区,从0开始编号
    kernel #→指定内核文件及传递给内核的参数
    参数 #→ro root=/path/to/DEVICE quiet
    initrd文件 #→通常为cpio归档,并使用gzip压缩;通常以.img作为文件名后缀;


(5)Kernel

       根据Grub内的定义,grub读取完毕后就把下面的工作交个内核了。kernel主要是完成系统硬件探测及硬件驱动的初始化,并且以读写的方式挂载根文件系统(根切换),那么这里就出现了一个“先有鸡还是先有蛋的文件了”,具体是什么那?

       要想访问真正的根文件系统(rootfs)的话,就必须加载根文件系统中的设备,这时根文件系统又没有挂载,要挂载根文件系统又得加载根文件系统中的驱动程序,哪怎么办呢?为了解决这个问题,这是就用到了initrd文件了。

       在来说下kernel初始化所要工作的内容做下简单总结:

探测硬件->加载驱动(initrd)->挂载根文件系统->rootfs(/sbin/init)

       这里要需要做一下说明:initrd和initramfs的区别,首先initrd是系统加载驱动时将内存模拟为磁盘设备,需要再次在内核中缓存,而initramfs却将内存直接模拟为文件系统,这样它就比起initrd显得更加的优越。所以在Centos5上面的initrd在后来的6上面改成了后者.所以在此我虽然用的是CentOS6.5但是请各位看官分清他们的不同之处即可.


(6)到此止内核空间的相关工作已经完成,内核空间的任务开始向用户空间转移,内核空间通过一个间接的initrd(微型linux)向用户空间的/sbin/init过渡,所以gurb开始引导内核转向initrd。initrd:一个虚拟的文件系统,里面有lib、bin、sbin、usr、proc、sys、var、dev、boot等一些目录,其实你会发现里面的目录有点像真的/对吧,所以我们称之为虚拟的根文件系统,作用就是将kernel和真的根文件系统建立关联关系,让kernel去initrd中加载根文件系统所需要的驱动程序,并以读写的方式挂载根文件系统,并让执行用户空间当中第一个进程init.

[root@Gmq ~]# mkdir /image #→新建文件夹image
[root@Gmq ~]# cp /boot/initramfs-2.6.32-431.el6.x86_64.img /image/ #→复制initramfs至/image目录下
[root@Gmq ~]# cd /image/
[root@Gmq image]# zcat initramfs-2.6.32-431.el6.x86_64.img | cpio –id #→将它解压到当前目录
97331 blocks
[root@Gmq image]# ls
bin      dracut-004-335.el6  init                initqueue-settled                    lib    pre-pivot    proc  sysroot  var
cmdline  emergency           initqueue           initqueue-timeout                    lib64  pre-trigger  sbin  tmp
dev      etc                 initqueue-finished  initramfs-2.6.32-431.el6.x86_64.img  mount  pre-udev     sys   usr
[root@Gmq image]#看到了initramfs这个映像文件所包含的文件bin,etc,dev,init,dev,lib,sbin,sys,sysroot、proc等,


下面通过截图大概看一下init这个脚本程序文件都做了些什么工作?

挂载:将initrd中的proc、sysfs挂载到当前的主分区中的相应目录

wKioL1MWv4ih5fCyAACGQKPK4hQ030.jpg

(图8)

通过mknod完成block 的创建

wKioL1MWv4jhw3ujAACSyXYmtXI949.jpg

(图9)

创建系统需要的目录并设定权限

wKioL1MWv_SyvtEGAACDiHDPXXo347.jpg

(图10)

尝试挂载根文件系统

wKioL1MWwErwJLsYAACISkgqM7o887.jpg

(图11)

最后完成根切换

wKioL1MWwH6xa3kkAAAaSPgBY2g837.jpg

(图12)

等等,其实还有好多的工作,貌似我就只认识这几个了.....看来English要加强了t_0003.gif


(7)init执行完毕以后会启动系统内的/etc/inittab文件,来完成系统系统的初始化工作。下面我在来分析一下inittab这个配置文件内的详细内容.(图15为CentOS6的intittab文件,图16为CentOS5的inittab配置文件)wKioL1MWwT_yLKaSAAJi_BFUs2c473.jpg

(图13)

上面6行英文注释主要是告诉我们一些工作是在哪些配置文件里面去配置的,

各个级别的定义:

0:halt  #→系统关机状态
1: single user mode #→单用户维护状态
2:multi user mode, without NFS #→多用户状态,不支持NFS功能
3: multi user mode, text mode     #→完整多用户模式、字符界面
4:reserved   #→系统保留,一般不使用
5: multi user mode, graphic mode  #→Xwindow系统
6: reboot   #→系统正常关闭并重启

/etc/inittab文件的格式及语法(注意它与CentOS6的区别)如下图:

wKioL1MWwfPgxN3qAAZqriNqhOU227.jpg

(图14)

发现和版本6的一些小区别了吧!虽然他们文件有一些差别,但是完成的任务确实一样的。
现在先了解一下这个文件的语法格式:

[选项]:[runlevel]:[动作]:[操作]

行为:

initdefault:设置默认运行级别,无需定义操作

sysinit:代表系统初始化操作选项

ctrlaltdel:定义组合键CtrlAltDel被按下时的动作

wait:等待系统切换至此级别时运行一次

respawn:当指定操作进程被关闭时立即再启动一次;

命令选项:

一些命令,不过通常都是脚本


下面说下inittab内定义的初始化脚本: /etc/rc.d/rc.sysinit,如图1所示那里已经总结出来该文件它的主要任务,由于文件较大,我就不发图了,各位看官可以阅读一下该文件就知道了.等那些操作执行完成后,系统就根据运行级别运行相关的服务脚本:/etc/rc.d/init.d/脚本和/etc/rc.d/rc#d

wKioL1MWwpnR-sZdAAEtzpYCafo935.jpg

(图15)

从上图可以看到与运行级别的各文件的功能了,下面我们再来看一下rc0-rc6目录都有什么东东,我打开rc3.d看一下:

wKiom1MWwxOThlFIAAODHkgK6JM879.jpg

(图16)

这些文件都是链接文件他们链接到了/etc/init.d/*目录下的各个程序的,例如ntpd这个脚本

wKioL1MWwu3SKw9pAACki89MyuU485.jpg

那K74或者S##开头的那些又是什么意思呢?

       其实K代表的是该服务下次启动将会是关闭的,不代表当前这服务就是关闭的,定义的只是下次重启系统后是关闭与否;

       S代表就是该服务下次启动将会是随系统启动而一起启动的,但是不代表当前他就是关闭的,定义的只是下次重启系统后是开启与否;

       后面的数字是众多服务在开机程序中的优先级别,他的取值是0-99,数字越小,优先级越高;

那我们怎么设置某一服务下次重启系统后是该关闭或者开启呢,下面介绍一个命令:

checkconfig
命令格式:
chkconfig [options] Service_Name [on|off]
    Options:--add #→添加程序服务
             --list #→列出当前系统上所有的服务对应的级别是关闭还是启动
             --del #→删除某个服务(只是删除链接文件,不删除原文件)
             --level [on|off] #→指定某个服务对应哪些级别是on或off

下面我举个例子来说一下:

查看指定服务的运行运行信息:0-6级别都是关闭的:

[root@Gmq ~]# chkconfig --list ntpd
ntpd            0:off   1:off   2:off    3:off    4:off    5:off    6:off
[root@Gmq ~]#

我们将该服务打开:  

[root@Gmq ~]# chkconfig ntpd on
[root@Gmq ~]# chkconfig --list ntpd
ntpd            0:off   1:off   2:on    3:on    4:on    5:on    6:off
[root@Gmq ~]#

有没有发现默认就打开了2345级别,只要系统重启后这个服务就会运行在2345这四个级别当中的某一个,当然至于哪一个可以自己决定;

下面我们看一下这个它的原文件都写了什么内容,能让chkconfig这个命令对其操作呢:

[root@Gmq ~]# vim /etc/init.d/ntpd
.......................
.......................
# chkconfig: - 58 74
# description: ntpd is the NTPv4 daemon. \
.......................
.......................

我们就看着两行信息就行啦,其他都是程序自己的一些信息了;

Chkconfig: - 58 74

 其中“-”表示的是运行级别,默认就代表2345(难怪上面的那个操作默认就开启2345级别了)

     "58" 代表指定启动时的优先级;“74”代表指定关闭时的优先级

     Description:代表的对这个脚本的一个描述
用户自定义开机启动程序,可以根据自己的需求将一些执行命令或是写到脚本/etc/rc.d/rc.local.当开机时就可以自动加载啦!


三、总结

Linux系统启动大概步骤总结如下:

1、加载bios硬件信息,并获取第一个启动设备的代号
2、读取第一个启动设备的mbr到物理内存,物理内存的内容就是Boot Loader了。
3、运行Boot Loader(如
grub,lilo等),初始化硬件设备,建立内存空间映射图。
4、根据Boot Loader设定的内核映像路径,系统读取内存映像,解压内核,尝试驱动所有硬件设备。
5、运行第一个程序/sbin/init。
6、执行第一个/etc/rc.d/rc.sysinit脚本程序
7、依据/etc/modules.conf装载内核模块。
8、执行不同运行级别的脚本程序
9、执行/etc/rc.d/rc.local脚本程序
10、执行/bin/login,进入等待用户登录状态。


系统初始化的大致内容总结如下:

1、硬件的初始化,图像界面启动的初始化(如果设置了默认启动基本)

2、主机RAID的设置初始化,device mapper 及相关的初始化,

3、检测根文件系统,以只读方式挂载

4、激活udev和selinux

5、设置内核参数 /etc/sysctl.conf

6、设置系统时钟

7、启用交换分区,设置主机名

8、加载键盘映射

9、激活RAID和LVM逻辑卷

10、挂载额外的文件系统 /etc/fstab

等等


最后根据mingetty程序调用login让用户登录->用户登录(完成系统启动)


在系统启动过程中主要的脚本和目录有哪些呢?我们可以概括一下

boot 目录

/grub 目录

/boot/grub/grub.conf 脚本

/boot/initrd+内核版本 文件

/initrd文件中的init文件

/initrd文件中的/proc/  /sys/    /dev/ 目录的挂载 及根的切换

/etc/inittab  脚本

/etc/rc.d/rc.sysinit  脚本

       这些重要的脚本和目录,当然还有其他重要的目录和文件,脚本等暂不列举啦。由此篇我们可以详细了解linux系统的启动和初始化过程,然后我们可以根据linux系统启动的过程和所用到的命令自己动手DIY一个微型linux系统,关于“gurb菜单加密/修复会近期总结后发表博文,期待各位大神拍砖.

《Linux系统-小倒腾之Linux DIY定制裁剪(附带简单网络功能)o_o》已发表!




t_0022.gif由于本人水平有限,以上学习总结内容不能保证准确无误,请自行鉴别.