Linux 启动过程


前言:

  Linux是一种自由和开放源代码的类UNIX操作系统。该操作系统的内核由林纳斯·托瓦兹在1991年10月5日首次发布。在加上用户空间的应用程序之后,成为Linux操作系统。Linux是自由软件和开放源代码软件发展中最著名的例子。

  Linux有许多常见的发行版本,如CentOS,Ubuntu,SUSE,Redhat ,NSDL等。像Ubuntu 每年的4月和10月都会出一个新的发行版本,CentOS 同样也是更新频繁,目的无非是为了以下三点:

1、修复一些bug和漏洞;

2、支持一些新硬件;

3、追求更高的性能和体验;


在上一篇 Windows的启动过程 ,操作系统启动过成功大致可以分为以下几步:

1、预引导

2、引导

3、加载内核

4、初始化内核

5、登录

同样,Linux操作系统也是按照这几步来实现引导和启动的,只是引导和启动程序不同而已;由于Linux发行版本众多且随着版本的升级,引导和启动过程也是存在一些差别的,本文将从CentOS 7 的引导和启动方式来进行讲解。

1、预引导阶段

1)BIOS 之加电自检:检查硬件是否正常

2)硬件检查正常,产生INT 13H中断,定位MBR程序并移交控制权给BootLoader。

注:
Windows 下的BootLoader 是Bootmgr(vista以后,xp是ntldr),Linux 常见的是GRUB,GRUB2以及LILO。
CentOS 7及之后的版本用的是GRUB2。

这里需要说明下MBR和BootLoader的关系:MBR 即主引导记录,它的大小是512字节,有三部分构成:BootLoader引导信息(前446个字节)、分区表信息(中间64个字节),结束符(55AA)。

下面给出我的机器硬盘信息如下:
Linux 启动过程_第1张图片
从上图可以看出机器只有一块硬盘,2个分区。我们再来看下该硬盘的前512字节值:
Linux 启动过程_第2张图片
我们可以看到最后是以55AA结束的。


在CentOS 7 中BootLoader 使用的GRUB2,grub2使用img文件,不再使用GRUB1 (CentOS 6 使用)中的stage1、stage1.5 和 stage2,GRUB2 程序是由多个img构成的,其中boot.img 承担了MBR的角色,grub2将boot.img转换后的内容安装到MBR(VBR或EBR)中的boot loader部分;信息如下:
在这里插入图片描述
大小为512字节,接着我们来看一下boot.img类容是否和MBR是一样的?boot.img内容如下:
Linux 启动过程_第3张图片
对比上面/dev/sda硬盘的前512个字节,中间确实有一部分是一样,但是不完全一样,因为是做了转化的。它的作用就是找到接下来要说的core.img。


2、引导阶段

1)根据BIOS选择的启动信息,动态生成core.img

在CentOS 7 中core.img 是由grub2-mkimage程序动态创建动态生成的,它的组成如下:
Linux 启动过程_第4张图片
i)如果启动设备是硬盘,即从硬盘启动时,core.img中的第一个扇区的内容就是diskboot.img。

ii)如果启动设备是光驱(cd-rom),即从光驱启动时,core.img中的第一个扇区的的内容就是cdboot.img。

iii)如果是从网络的PXE环境启动,core.img中的第一个扇区的内容就是pxeboot.img。

注:
这里的kernel.img 并不是linux 内核,它只是GRUB2的核心部分,和操作系统的内核无关。
modules:可以动态加载的模块。

这些img原始信息是存放在/usr/lib/grub/i386-pc 目录下的,其中/boot/grub2/i386-pc目录下的boot.img 也是在安装grub时从这里拷贝过去的。
Linux 启动过程_第5张图片
2)加载core.img 到内存

由于MBR 大小仅有512个字节,因此要想完成更多的功能,还需要加载更大点的程序到内存中来,因此在这个阶段就需要由前面的boot.img 来引导或者找到更大的程序,但是系统在没启动时,MBR根本找不到文件系统,也就找不到大程序所存放的位置,所以需要加载能够识别文件系统的驱动 ,而core.img 就可以完成这个动作,即core.img 能够完成GRUB1 在1.5 阶段完成的任务,因此需要将core.img 加载到内存中来。 core.img 文件会存储在第一个分区的开始位置,即在扇区 63 和 MBR(扇区 0)之间遗留下 62 个 512 字节的扇区(共 31744 字节)中。
在这里插入图片描述
大小是26703 ,尽管这个不固定大小,但是31744 字节空间是完全可以存放下的。

注:
细心的朋友可能注意到kernel.img 的大小都已经大于core.img大小了,其实因为这个core.img是经压缩过的。

3)加载驱动识别文件系统

core.img 会包含一些通用的文件系统驱动程序,如标准的 EXT 和其它的 Linux 文件系统,如 FAT 和 NTFS 等。GRUB2 的 core.img 远比更老的 GRUB1 阶段 1.5 更复杂且更强大。能够识别文件系统后,才能将存于/boot 目录下的文件,其中就包括Linux 内核和运行时加载的模块等文件读取。


3、加载内核

1)加载内核到内存

bootloader (这里是core.img)从硬盘中读取内核到内存,除了读取内核还会将一个虚拟文件系统(或叫内存文件系统)读入内存;内存文件系统 initramfs 是经过gzip 的 cpio 归档,其中包含启动时所有必要的硬件内核模块、初始化脚本等。内核的相关文件位于 /boot 目录下,这些内核文件可以通过其文件名进行识别,其文件名均带有前缀 vmlinuz。

2)将控制权移交至内核

4、初始化内核

1)加载驱动并挂载真正的根文件系统

​ 内核初始化在 initramfs 中找到驱动程序的所有硬件,Kernel会以只读方式挂载根文件系统,当根文件系统被挂载后,内核与文件由虚拟文件系统(内存文件系统)切换至真实的系统根文件系统并将initramfs 从内存中移除。

注:
因为Kernel为了精简,只保留了最基本的模块,因此,Kernel上并没有各种硬件的驱动程序,也就无法识rootfs所在的设备,故产生了initramfs 这个文件,该文件装载了必要的驱动模块,当Kernel启动时,可以从initramfs文件中装载驱动模块,直到挂载真正的rootfs,然后将initramfs 从内存中移除。

我们可以通过lsinitrd 命令查看initramfs文件内容,如下:
Linux 启动过程_第6张图片
由于执行后命令后,内容会比较多,几乎和真实的根“/”系统下面目录内容差不多。这里就不截图了。感兴趣的可以自己看下。

2)systemed初始化阶段

​ CentOS7中我们的初始化(init)进程变为了systemd。执行默认target文件/etc/systemd/system/default. target(这是一个软链接,与默认运行级别有关)。然后执行sysinit.target来初始化系统和basic.target来准备操作系统。接着启动multi-user.target下的本机与服务器服务,并检查/etc/rc.d/rc.local文件是否有用户自定义脚本需要启动。最后执行multi-user下的getty.target及登录服务,检查default.target是否有其他的服务需要启动,最后等待用户登录。

注:
/etc/systemd/system/default.target指向了/lib/systemd/system/目录下的graphical.target或multiuser.target。而graphical.target依赖multiuser.target,multiuser.target依赖basic.target,basic.target依赖sysinit.target,所以倒过来执行。

这里我们可以看出default.target是/lib/systemd/system/multi-user.targetd的软连接,因为其运行在level 3;
在这里插入图片描述
进入/lib/systemd/system 目录,我们发现会有几个runlevel *.target开头的文件,查看详细信息如下:
Linux 启动过程_第7张图片
我们发现这个几个文件都是软连接,这其实是为了兼容老版本的。我们发现runlevel 2|3|4.target 都是指向multi-user.target文件的。那从default.target看只知道运行 multi-user.target,但是具体是2还是3级呢?(4级保留,未为使用)。可以通过如下命令查看:

[root@localhost system]# runlevel
N 3
或
[root@localhost system]# who -r
         run-level 3  2020-03-20 10:14
注:
  runlevel,运行级别,不同的级别会启动的服务不一样,init会根据定义的级别去执行相应目录下的脚本,Linux的启动级别分为以下几种:

  0:关机模式
  1:单一用户模式(直接以管理员身份进入)
  2:多用户模式(无网络)
  3:多用户模式(命令行)
  4:保留
  5:多用户模式(图形界面)
  6:重启

5、登录

1)鉴权

初始化进程会启动进程getty,getty等待用户输入用户名,当用户输入用户名后就会启动login程序,该程序负责认证用户。用户认证信息是从/etc/passwd 或 /etc/shadow 得到用户名和密码信息的,以及认证成功后的工作目录的与交互式shell程序。类似于Windows认证成功时运行的explorer.exe,也就是一个Windows 的 shell 程序。

/etc/passwd中一行记录对应着一个用户,每行记录又被冒号(:)分隔为7个字段,其格式和具体含义如下:
  用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录Shell

如我机器的 /etc/passwd 内容如下:
Linux 启动过程_第8张图片
/etc/shadow 这个文件的每行代表一个用户,同样使用":"作为分隔符,划分为 9 个字段

​ 1、账户名称
  2、加密后的密码,如果这一栏的第一个字符为!或者*的话,说明这是一个不能登录的账户,ubuntu默认的就不启用root账户。
  3、最近改动密码的日期(这个是从1970年1月1日算起的总的天数)。
  4、密码不可被变更的天数:设置了这个值,则表示从变更密码的日期算起,多少天内无法再次修改密码,如果是0的话,则没有限制
  5、密码需要重新变更的天数:如果为99999则没有限制
  6、密码过期预警天数
  7、密码过期的宽恕时间:如果在5中设置的日期过后,用户仍然没有修改密码,则该用户还可以继续使用的天数
  8、账号失效日期,过了这个日期账号就无法使用
  9、保留的

如我机器的 /etc/passwd 内容如下:
Linux 启动过程_第9张图片

注:为什么有了/etc/passwd 文件还要有/etc/shadow文件呢?

/etc/passwd 文件,由于该文件允许所有用户读取,易导致用户密码泄露,因此 Linux 系统将用户的密码信息从 /etc/passwd 文件中分离出来,并单独放到了此文件中。
/etc/shadow 文件只有 root 用户拥有读权限,其他用户没有任何权限,这样就保证了用户密码的安全性。

2)登录成功,加载环境变量

上面如果鉴权成功后,接着就会加载一些环境变量,加载顺序:

/etc/profile --> /etc/profile.d/*.sh --> ~/.bash_profile --> ~/.bashrc --> /etc/bashrc

注:前面两个是全局配置文件,后面三个是个人配置文件;其
1. profile类的文件:
   ​    设定环境变量
   ​    运行命令或脚本
2. bashrc类的文件:
   ​    设定本地变量
   ​    定义命令别名

好了,到这里就能看到我们个性化的终端或界面了。如果有写的不对或不周的地方欢迎指正。

CentOS6启动流程(含详细流程图)

你可能感兴趣的:(Linux,知识,内核,操作系统,linux,面试,程序人生)