概述

linux启动时我们会看到许多启动信息,其过程可以分为5个阶段:

  • BIOS自检
  • 读取MBR
  • 通过Boot Loader引导系统加载
  • 加载initramfe虚拟文件系统
  • 加载内核
  • 运行systemd

init程序的类型:

  • SysV: init, CentOS 5之前, 配置文件: /etc/inittab。
  • Upstart: init,CentOS 6, 配置文件: /etc/inittab, /etc/init/*.conf。
  • Systemd: systemd, CentOS 7,配置文件: /usr/lib/systemd/system、 /etc/systemd/system。

BIOS自检

BIOS(Basic Input Output System,基本输入输出系统)是固化在主板上一个 ROM(只读存储器)芯片上的程序,主要保存计算机的基本输入/输出信息、系统设置信息、开机自检程和系统自启动程序,用来为计算机提供最底层和最直接的硬件设置于控制。

BIOS的上电自检POST(Power-on self test),主要负责检测系统外围关键设备(如:CPU、内存、显卡、I/O、键盘鼠标等)是否正常。例如,最常见的是内存松动的情况,BIOS自检阶段会报错,系统就无法启动起来;

读取MBR(Main Boot Record,主引导记录)

当POST完成后,便会执行一段小程序用来枚举本地设备并对其初始化。这一步主要是根据我们在BIOS中设置的系统启动顺序来搜索用于启动系统的驱动器,如硬盘、光盘、U盘、软盘和网络等。我们以硬盘启动为例,系统找到BIOS所指定的硬盘后,读取硬盘驱动器的第一个扇区的MBR(将其复制到0×7c00地址所在的物理内存中。其实被复制到物理内存的内容就是Boot Loader,而具体到的电脑,那就是lilo或者grub)。实际上BIOS并不关心启动设备第一个扇区中是什么内容,它只是负责读取该扇区内容。

MBR 也就是主引导记录,位于硬盘的 0 磁道、0 柱面、1 扇区中,主要记录了启动引导程序和磁盘的分区表。我们通过图 1 来看看 MBR 的结构。


图  1 MBR的结构

MBR 共占用了一个扇区,也就是 512 Byte。其中 446 Byte 安装了启动引导程序,其后 64 Byte 描述分区表,最后的 2 Byte 是结束标记。我们已经知道,每块硬盘只能划分 4 个主分区,原因就是在 MBR 中描述分区表的空间只有 64 Byte。其中每个分区必须占用 16 Byte,那么 64 Byte 就只能划分 4 个主分区。每个分区的 16 字节的规划如表 2 所示。

存储字节 数据内容及含义
第 1 字节 引导标志
第 2 字节 本分区的起始磁道号
第 3 字节 本分区的起始扇区号
第 4 字节 本分区的起始柱面号
第 5 字节 分区类型,可以识别主分区和扩展分区
第 6 字节 本分区的结束磁道号
第 7 字节 本分区的结束扇区号
第 8 字节 本分区的结束柱面号
第 9~12 字节 本分区之前已经占用的扇区数
第 13~16 字节 本分区的总扇区数

MBR 中最主要的功能就是找到并加载启动引导程序。

通过Boot Loader引导系统加载

由于GRUB 的功能非常强大,MBR(446字节)空间只能安装 GRUB 的最小的主程序,而把GRUB 的相关配置文件放到了文件系统中。 所以Linux 把 GRUB 的程序分成三个阶段来执行。

Stage 1:执行GRUB主程序

第一阶段是用来执行 GRUB 主程序的,这个主程序必须放在启动区中(也就是 MBR 或者引导扇区中)。但是 MBR 太小了,所以只能安装 GRUB 的最小的主程序,而不能安装 GRUB 的相关配置文件。这个主程序主要是用来启动 Stage 1.5 和 Stage 2 的。

Stage 1.5:识别不同的文件系统

Stage 2 比较大,只能放在文件系统中(分区),但是 Stage 1 此时还不能识别不同的文件系统,所以不能直接加载 Stage 2。这时需要先加载 Stage 1.5,由 Stage 1.5 来加载不同文件系统中的 Stage 2(将stage2载入内存并执行)。

还有一个问题,难道 Stage 1.5 不是放在文件系统中的吗?如果是,那么 Stage 1 同样不能找到 Stage 1.5。其实,Stage 1.5 还真没有放在文件系统中,而是在安装 GRUB 时,直接安装到紧跟 MBR 之后的 32KB 的空间中,这段硬盘空间是空白无用的,而且是没有文件系统的,所以 Stage 1 可以直接读取 Stage 1.5。读取了 Stage 1.5 就能识别不同的文件系统,才能加载 Stage 2。

Stage 2:加载GRUB的配置文件

Stage 2 阶段主要就是加载 GRUB 的配置文件 /boot/grub2/grub.cfg,然后根据配置文件中的定义,加载内核和虚拟文件系统。接下来内核就可以接管启动过程,继续自检与加载硬件模块了。

启动引导程序的作用

每种操作系统的启动引导程序都是不同的(BootLoader是严重地依赖于硬件而实现的),不同的操作系统只有使用自己的启动引导程序才能加载自己的内核。如果我的服务器上只安装了一个操作系统,那么这个操作系统的启动引导程序就会安装在 MBR 中。BIOS 调用 MBR 时读取出启动引导程序,就可以加载内核了。

如果服务器中安装了多个操作系统,很明显,一个 MBR 是不够用的。每块硬盘只能有一个 MBR 是不能更改的,所以不可能増加 MBR 的数量。系统只能在每个文件系统(可以看成分区)中单独划分出一个扇区,称作引导扇区(Boot Sector)。每个分区的引导扇区中也能安装启动引导程序,也就是说,在 MBR 和每个单独分区的引导扇区中都可以安装启动引导程序。这样多个操作系统才能安装在同一台服务器中(每个操作系统要安装在不同的分区中),而且每个操作系统都是可以启动的。

但是 BIOS 只能找到 MBR 中的启动引导程序,而找不到在分区的引导扇区中的启动引导程序。 要想完成多系统启动,则通过安装到 MBR 中的启动引导程序(GRUB)调用在分区的引导扇区中的其他启动引导程序。不过需要注意的是,Windows 的启动引导程序不能调用 Linux 的启动引导程序,所以我们一般建议先安装 Windows,后安装 Linux,是为了将 Linux 的启动引导程序安装到 MBR 中,覆盖 Windows 的启动引导程序。

当然,这个安装顺序不是绝对的,就算最后安装了 Windows,我们也可以通过手工再安装 GRUB 的方法,来保证 MBR 中安装的还是 Linux 的启动引导程序。
下图为我们展示了启动引导程序的作用。


图 2 启动引导程序的作用

Linux /boot/grub2/目录

centos7使用/boot/grub2目录,而不再是grub目录; GRUB(启动引导程序)的配置文件主要放置在 /boot/grub2/ 目录中。不过 GRUB 的配置文件有两个:/boot/grub2/grub.conf 和 /boot/grub/menu.lst,这两个配置文件是软链接,所以修改哪一个都可以。

加载内核

当系统引导完成后,首先会去加载装载程序的配置文件:/etc/grub.d/ /etc/default/grub /boot/grub2/grub.cfg,根据grub配置文件设定的内核镜像所在路径,系统加载内核镜像到内存中,并进行解压缩操作。当解压缩内核完成后,系统将解压后的内核放置在内存之中,并将控制权转交给内核,然后调用start_kernel()函数来启动一系列的初始化函数并初始化各种设备,其中包括CPU、I/O、存储设备等,完成Linux核心环境的建立。

当 GRUB 加载了内核之后,内核首先会再进行二次系统的自检,而不一定使用 BIOS 检测的硬件信息。这时内核终于开始替代 BIOS 接管 Linux 的启动过程了。

内核完成再次系统自检之后,开始采用动态的方式加载每个硬件的模块,这个动态模块大家可以想象成硬件的驱动(默认 Linux 硬件的驱动是不需要手工安装的,如果是重要的功能,则会直接编译到内核当中;如果是非重要的功能,比如硬件驱动会编译为模块,则在需要时由内核调用)。

/boot目录

[root@localhost ~]# ls /boot/
#内核的配置文件,内核编译时选择的功能与模块
config-3.10.-.el7.x86_64
grub
#启动引导程GTUB的数据目录
grub2
#虚拟文件系统
initramfs--rescue-f6f8ed7a7aca4093bcb3a2869a2b3abf.img
initramfs-3.10.-.el7.x86_64.img
initramfs-3.10.-.el7.x86_64kdump.img
initrd-plymouth.img
#boot分区的备份目录
lost+found
#模块符号信息
symvers-3.10.-.el7.x86_64.gz
#内核功能和内存地址的对应列表
System.map-3.10.-.el7.x86_64
#用于启动的Linux内核。这个文件是一个压缩的内核镜像
vmlinuz--rescue-f6f8ed7a7aca4093bcb3a2869a2b3abf
vmlinuz-3.10.-.el7.x86_64

在Linux中,会把不重要的功能编译成内核模块,需要时再调用,从而保证了内核不会过大。在多数 Linux 中,都会把硬件的驱动程序编译为模块, 这些模块保存在 /lib/modules/ 目录中。常见的 USB、SATA 和 SCSI 等硬盘设备的驱动,还有一些特殊的文件系统(如 LVM、RAID 等)的驱动,都是以模块的方式来保存的。

如果 Linux 安装在 IDE 硬盘之上,并且采用的是默认的 ext3/4 文件系统,那么内核启动后加载根分区和模块的加载都没有什么问题,系统会顺利启动。但是如果 Linux 安装在 SCSI 硬盘之上,或者采用的是 LVM 文件系统,那么内核在加载根目录之前是需要加载 SCSI 硬盘或 LVM 文件系统的驱动的。

SCSI 硬盘和 LVM 文件系统的驱动都放在硬盘的 /lib/modules/ 目录中,既然内核没有办法识别 SCSI 硬盘或 LVM 文件系统,那怎么可能读取 /lib/modules/ 目录中的驱动呢?Linux 给出的解决办法是使用 initramfs 这个虚拟文件系统来处理这个问题。

加载initramfe虚拟文件系统

通过挂载临时根目录initramfs加载核心模块(驱动程序...),然后卸载临时根目录,挂载真正的根目录。

initramfs与initrd类似,也是初始化好了且存在于ram中的,可以压缩也可以不压缩。可以通过启动引导程序加载到内存中,然后解压缩并在内存中生成一个根目录,并且这个文件系统能够提供一个可执行程序,通过该程序来加载启动过程中所需的内核模块,比如 USB、SATA. SCSI 硬盘的驱动和 LVM、RAID 文件系统的驱动。

也就是说,通过 initramfs 虚拟文件系统在内存中模拟出一个根目录,然后在这个模拟根目录中加载 SCSI 等硬件的驱动,就可以加载真正的根目录了,之后才能调用 Linux 的第一个进程。

Initramfs 虚拟文件系统主要有以下优点:

  • initramfs 随着其中数据的増减自动増减容量。
  • 在 initramfs 和页面缓存之间没有重复数据。
  • initramfs 重复利用了 Linux caching 的代码,因此几乎没有増加内核尺寸,而 caching 的代码已经经过良好测试,所以 initramfs 的代码质量也有保证。
  • 不需要额外的文件系统驱动。

其实大家只需要知道 initramfs 是为了在内核中建立一个模拟根目录,这个模拟根目录是为了可以调用 USB、SATA、SCSI、LVM、RAID 等硬盘接口或文件系统的驱动模块,加载了驱动模块后才可以加载真正的系统根目录。我们可以通过示意图 1 来表示这个过程。


图 1 内核启动流程

initramfs 是一个仿真根目录,这个根目录中的内容如下:

[root@localhost ~]# mkdir /tmp/initramfs
#建立测试目录
[root@localhost ~]# cp/boot/
initramfs-2.6.-.el6.i686.img/tmp/initramfs/
#复制initramfs文件
[root@localhost ~]# cd /tmp/initramfs/
[root@localhost initramfs]# file
initramfs-2.6.-.el6.i686.img
initramfe-2.6.-.el6.i686.img:gzip compressed
data,from Unix,last modified:
Wed Apr :: , max compression
#查看文件类型,发现这个文件是一个使用gzip命令打包的压缩包
[root@localhost initramfs]# mv initramfs-2.6.-.el6.i686.imginitramfs-2.6.-.el6.i686.img.gz
#修改文件的扩展名为.gz
[root@localhost initramfs]# gunzip
initramfs-2.6.-.el6.i686.img.gz
#解压缩
[root@localhost initramfs]# ls
initramfs-2.6.-.el6.i686.img
[root@localhost initramfs]# file
initramfs-2.6.-.el6.i686.img
initramfe-2.6.-.el6.i686.img: ASCII cpio archive (SVR4withnoCRC)
#查看文件类型,使用cpio命令的压缩文件
[root@localhost initramfs]# cpio -ivcdu <initramfs-2.6.-.el6.i686.img
#解压缩
[root@localhost initramfs]#ll
总用量34512
drwxr-xr-x. root root 4月 : bin
drwxr-xr-x. root root 月 : cmdline
drwxr-xr-x. root root 4月 : dev
-rw-r--r--. root root 月 : dracut--.el6
drwxr-xr-x. root root 月 : emergency
drwxr-xr-x. root root 4月 : etc
-rwxr-xr-x. root root 4月 : init
drwxr-xr-x. root root 月 : initqueue
drwxr-xr-x. root root 月 : initqueue-finished
drwxr-xr-x. root root 月 : initqueue-settled
drwxr-xr-x. root root 月 :
initqueue-timeout
-rw-r--r--. root root 月 : initramfs-2.6.-.el6.i686.img
drwxr-xr-x. root root 4月 : lib
…省略部分输出…

这就是initramfs虚拟文件系统中的内容,是一个伪根目录。

运行systemd

Systemd概述:systemd即为system daemon [ˈdi:mən] 守护进程,是linux下的一种init软件,开发目标是提供更优秀的框架以表示系统服务间的依赖关系,并依此实现系统初始化时服务的并行启动,同时达到降低Shell的系统开销的效果,最终代替现在常用的System V与BSD风格init程序。

在内核加载完毕,并完成硬件检测与驱动程序加载后,主机硬件已经准备完毕,内核会主动呼叫第一个进程,为用户提供合适的工作环境。RHEL/CentOS 7系统中已经替换掉了熟悉的初始化进程服务System V init正式采用全新的systemd初始化进程服务。systemd初始化进程服务采用了并发启动机制,开机速度得到了不小的提升。

Systemd配置文件:

  • /usr/lib/systemd/system/ #这个目录存储每个服务的启动脚本,类似于之前的/etc/init.d/
  • /run/systemd/system/ #系统执行过程中所产生的服务脚本,比上面目录优先运行
  • /etc/systemd/system/ #管理员建立的执行脚本,类似于/etc/rc.d/rcN.d/Sxx类的功能,比上面目录优先运行

当第一个进程创建完毕后,使用default.target进入开启流程(假设是multi-user.target)
        执行sysinit.target初始化系统(检测硬件,载入所需的核心模组)、basic.target准备系统(载入硬件驱动和防火墙相关任务)
        执行multi-user.target下面的服务(如果启动了/etc/rc.d/rc.local,则需要启动里面的命令)
        执行multi-user.target下的/etc/rc.d/rc.local
        启动tty
        如果运行级别是graphical.target则会启动图形桌面;

centos7"运行级别"概念

centos7表面是有“运行级别”这个概念,实际上是为了兼容以前的系统,每个所谓的“运行级别”都有对应的软连接指向,默认的启动级别时/etc/systemd/system/default.target,根据它的指向可以找到系统要进入哪个模式

cenos6运行级别 cenos7运行级别 含 义
0 runlevel0.target, poweroff.target 关机
1 runlevel1.target, rescue.target 单用户模式,可以想象为 Windows 的安全模式,主要用于系统修复
2 runlevel2.target, multi-user.target 不完全的命令行模式,不含 NFS 服务
3 runlevel3.target, multi-user.target 完全的命令行模式,就是标准字符界面
4 runlevel4.target, multi-user.target 系统保留
5 runlevel5.target, graphical.target 图形模式
6 runlevel6.target, reboot.target 重新启动

查看系统默认运行级别

[root@localhost ~]# systemctl get-default
graphical.target

查看系统有哪些target

[root@localhost ~]# ls /lib/systemd/system/*.target
/lib/systemd/system/basic.target
/lib/systemd/system/default.target
/lib/systemd/system/runlevel0.target
/lib/systemd/system/runlevel1.target
/lib/systemd/system/runlevel2.target
/lib/systemd/system/runlevel3.target
/lib/systemd/system/runlevel4.target
/lib/systemd/system/runlevel5.target
/lib/systemd/system/runlevel6.target

修改默认启动运行级别(永久生效)

[root@student ~]# systemctl set-default TARGET.target

Linux系统启动管理 系统启动流程的更多相关文章

  1. Linux操作系统-CentOS7启动流程和服务管理

    Linux操作系统-CentOS7启动流程和服务管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.systemd POST --> Boot Sequence --&g ...

  2. Linux操作系统-CentOS6启动流程和服务管理

    Linux操作系统-CentOS6启动流程和服务管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Linux组成 1>.Linux: kernel+rootfs ker ...

  3. Linux内存管理专题

    Linux的内存管理涉及到的内容非常庞杂,而且与内核的方方面面耦合在一起,想要理解透彻非常困难. 在开始学习之前进行了一些准备工作<如何展开Linux Memory Management学习?& ...

  4. 启动期间的内存管理之bootmem_init初始化内存管理–Linux内存管理(十二)

    1. 启动过程中的内存初始化 首先我们来看看start_kernel是如何初始化系统的, start_kerne定义在init/main.c?v=4.7, line 479 其代码很复杂, 我们只截取 ...

  5. 启动期间的内存管理之初始化过程概述----Linux内存管理(九)

    在内存管理的上下文中, 初始化(initialization)可以有多种含义. 在许多CPU上, 必须显式设置适用于Linux内核的内存模型. 例如在x86_32上需要切换到保护模式, 然后内核才能检 ...

  6. Linux时间管理涉及数据结构和传统低分辨率时钟的实现

    上篇文章大致描述了Linux时间管理的基本情况,看了一些大牛们的博客感觉自己写的内容很匮乏,但是没办法,只能通过这种方式提升自己……闲话不说,本节介绍下时间管理下重要的数据结构 设备相关数据结构 // ...

  7. Linux的开机启动流程

    Linux的开机启动流程 1.开机BIOS自检                                             --> 检查CPU,硬盘等硬件信息 2.MBR[Major ...

  8. linux内存管理

    一.Linux 进程在内存中的数据结构 一个可执行程序在存储(没有调入内存)时分为代码段,数据段,未初始化数据段三部分:    1) 代码段:存放CPU执行的机器指令.通常代码区是共享的,即其它执行程 ...

  9. python第二天-linux权限管理

    (1)linux登陆密码忘了,怎么办? 把系统重启,在进入系统之前不断的按键盘左上角的"Esc"键会进入这样一个画面,按键盘上的e进入编辑. 进入这个画面以后,通过键盘的上下方向键 ...

随机推荐

  1. 第一百五十八节,封装库--JavaScript,ajax说明

    封装库--JavaScript,ajax说明 封装库ajax()方法,ajax通讯方法,跨页面向动态页面发送或获取数据 /** ajax()方法,ajax通讯方法,跨页面向动态页面发送或获取数据 * ...

  2. Ajax.BeginForm提示不支持live属性或方法的错误

    解决: 在nuget下载最新版本的jquery.unobtrusive-ajax.min.js文件 Ajax异步请求: 引用JS: <script type="text/javascr ...

  3. java算法-数学之美二

    上一章已经说过利用数学思想来解决程序算法问题,实际上就是找规律.这在我们上学时经常遇到,比如给出一段数字,求某一个位置该填写什么数,只要找到规律那就迎刃而解.好了,废话不多说,再来看看案例分析.    ...

  4. SRM 719 Div 1 250 500

    250: 题目大意: 在一个N行无限大的网格图里,每经过一个格子都要付出一定的代价.同一行的每个格子代价相同. 给出起点和终点,求从起点到终点的付出的最少代价. 思路: 最优方案肯定是从起点沿竖直方向 ...

  5. 开发新手教程【三】Arduino开发工具

    Arduino开发环境搭建 获取Arduino IDE开发工具 下载地址 :http://arduino.cc/en/Main/Software 能够下载release 版.Beta版和前期版本号 A ...

  6. oauth 2

    OAuth2是基于HTTP的认证API,一般与OAuth2搭配的API也是基于HTTP的REST风格API(比如新浪微博和github),很多人一定想过是否可以直接从浏览器端调用REST API. 我 ...

  7. 使用python封装get+post请求

    思路: 将平时用的多的get和post请求封装,提高代码重用率. 其中Session类可以通过实例化,保存cookie信息,可以在程序结束前多次通过保存的cookie信息保持登录状态的访问. 那么为什 ...

  8. Docker for window 无法共享磁盘

    Docker for window 无法共享主机磁盘,环境如下: 操作系统: windown10 Docker version 18.09.0, build 4d60db4 症状如下: 如图,点击ap ...

  9. No transactional EntityManager available; nested exception is javax.persistence.TransactionRequiredException: No transactional EntityManager available

    参考地址:http://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/ ...

  10. 判断 checkbox 是否选中以及 设置checkbox选中

    //判断checkbox 是否选中 $("#id").is(":checked");//选中,返回true,没选中,返回false //设置checkbox为选 ...