认识Linux系统的启动

在《Linux初步》这门课上,我们实现了从内核出发,定制自己的Linux系统。要了解Linux,让我们从开机说起。

  • 本文使用的操作系统

1. 启动流程

​ 以个人计算机为例,当按下开机键时,计算机硬件会读取BIOS来加载硬件信息及进行硬件系统的自我测试,之后系统会主动读取第一个可启动设备,此时就可以读入引导装载程序了。

​ 引导装载程序可以指定使用哪个内核文件来启动,并实际加载内核到内存中进行解压缩与执行,然后内核就在内存中开始活动,等到内核检测硬件与加载程序执行完毕后,操作系统就完全跑起来了。

​ 主机系统开始运行后,,此时Linux才会调用外部程序开始准备软件执行的环境,并且实际加载所有系统运行所需要的软件程序,最后系统就会进入等待登入页面。整体来说,流程如下:

  1. 加载BIOS的硬件信息与自我测试,依据设置获得第一个可启动设备
  2. 读取并执行第一个启动设备内MBR的boot Loader(即grub,spfdisk等程序)
  3. 依据boot loader的设置加载Kernel,Kernel就开始检测硬件与加载驱动程序。
  4. 硬件驱动成功后,Kernel会调用Init进程,init会取得run-level信息
  5. init执行 /etc/rc.d/rc.sysinit档案来准备软件执行的作业环境(如网络、时区等)
  6. init执行run-level的服务
  7. init执行/etc/rc.d/rc.local
  8. init执行终端机仿真程序mingetty来启动login

2. BootLoader

​ 加载BIOS与开机自检后,就进入了BootLoader环节,为什么要有bootloader呢?因为不同的操作系统的文件系统格式不同,所以我们需要一个开机管理进程来处理核心文档加载的问题。bootloader安装在开机装置的第一个扇区内,也就是MBR。

​ 每个操作系统都有一块启动扇区,所以都有自己的boatloader,比如Linux系统的grub和Windows的windows boot manager。虽然各个操作系统都可以安装一份boot loader到boot sector中,但是系统MBR只有一个,所以在bootloader中,我们要通过“选单”来选择我们的操作系统。此时我们要提一提boatload的功能了。boatloader的功能如下:

  1. 提供选单:选择开机项目
  2. 载入核心文档:指向开机程序段
  3. 转交其他loader

​ 我们以Linux为例,Linux的grub用来管理开机程序,当我们选择一个内核版本时,系统会进入加载kernel环节;我们也可以选择开启windows,这时windows的loader会接管开机程序,所以windows才可以启动。

3. 加载Kernel与Initrd

​ 当我们由boot loader的管理开始读取核心文档后,Linux就会将核心解压到主储存器中,然后开始测试与驱动周边装置,包括ROM,CPU,网卡与声卡等。在Linux系统中,我们可以在/boot中中发现取名为vmlinuz的文件,这就是kernel

1
2
3
4
5
6
7
➜ /boot ll
总用量 59M
config-2.6.32-754.18.2.el6.x86_64 #此版本核心被编译时选择的功能与模块配置
grub #设置引导,管理开机程序
initramfs-2.6.32-754.18.2.el6.x86_64.img #虚拟文件系统档
System.map-2.6.32-754.18.2.el6.x86_64#核心功能放到内存地址的对应表
vmlinuz-2.6.32-754.18.2.el6.x86_64 #kernel,核心档案

​ Linux核心是可以通过动态加载核心模块的,如USB,DATA,SCSI等,这些模块放在/lib/modules中,但是核心不认识你的硬盘,所以需要加载硬盘驱动,但是我们此时又读不了硬盘,无法挂载根目录,怎么办?此时我们就需要用initrd虚拟文件系统档来处理。

​ !)

Linux系统启动流程

首先我们了解一下initrd里面都有什么

  1. 将/boot/initrd 复制到/tmp/initrd中
1
2
3
mkdir /tmp/initrd
cp /boot/initramfs-2.6.32-754.18.2.el6.x86_64.img /tmp/initrd
cd /tmp/initrd
  1. 解压文档
1
2
3
mv initramfs-2.6.32-754.18.2.el6.x86_64.img initrd.img.gz
gzip initrd.img.gz
cpio -i < initrd.img
  1. 观察文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
drwxr-xr-x. 2 zrs zrs 4.0K 9月   4 19:59 bin
drwxr-xr-x. 2 zrs zrs 4.0K 9月 4 19:59 cmdline
drwxr-xr-x. 3 zrs zrs 4.0K 9月 4 19:59 dev
-rw-r--r--. 1 zrs zrs 19 6月 19 2018 dracut-004-411.el6
drwxr-xr-x. 2 zrs zrs 4.0K 9月 4 19:59 emergency
drwxr-xr-x. 6 zrs zrs 4.0K 9月 5 04:56 etc
-rwxr-xr-x. 1 zrs zrs 8.8K 6月 19 2018 init
drwxr-xr-x. 2 zrs zrs 4.0K 9月 4 18:47 initqueue
drwxr-xr-x. 2 zrs zrs 4.0K 9月 4 18:47 initqueue-finished
drwxr-xr-x. 2 zrs zrs 4.0K 9月 4 18:47 initqueue-settled
drwxr-xr-x. 2 zrs zrs 4.0K 9月 4 19:59 initqueue-timeout
-rwxr-xr-x. 1 zrs zrs 51M 9月 4 19:56 initrd.img
drwxr-xr-x. 7 zrs zrs 4.0K 9月 5 02:42 lib
drwxr-xr-x. 2 zrs zrs 4.0K 9月 4 19:59 lib64
#·····后续省略

我们发现这里也有一个init,用vim打开init后,我们可以发现其中有挂载内存虚拟文件系统和建立系统的装置,并且还有加载核心模块的驱动程序,有了这些,kernel就可以正确运作了

1
2
3
4
5
6
7
8
#!/bin/nash			<==使用类似 bash 的 shell 来执行
····
mount -t proc /proc /proc #<==挂载内存的虚拟文件系统
····
mknod /dev/null c 1 3 #<==建立系统所需要的各项装置
····
insmod /lib/ehci-hcd.ko #<==加载各项核心模块,即驱动程序
····

⚠注: 是否没有 initrd 就无法顺利开机? 答: 不一定。需要 initrd 最重要的原因是,当开机时无法挂载根目录的情况下, 此时就一定 需要 initrd ,例如你的根目录在特殊的磁盘接口 (USB, SATA, SCSI) , 戒者是你的文件系 统较为特殊 (LVM, RAID) 等等,扄会需要 initrd。如果你的 Linux 是安装在 IDE 接口的磁盘上,并且使用默认的 ext2/ext3 文件系统, 那么 不需要 initrd 也能够顺利的开机进入Linux 。