操作系统的启动经历了什么?
目录
本文主要摘录自阮一峰老师的博客,想要查看原文的请访问原文
¶计算机的启动过程
“pull oneself up by one’s bootstraps”——通过拽着鞋带将自己拉起来
¶第一阶段:BIOS
上个世纪 70 年代初,“只读内存”(read-only memory,缩写为 ROM)发明,开机程序被刷入 ROM 芯片,计算机通电后,第一件事就是读取它
这块芯片里的程序叫做基本输入输出系统(Basic Input/Output System),简称 BIOS
¶硬件自检
BIOS 程序首先检查,计算机硬件能否满足运行的基本条件,这叫做「硬件自检」(Power-On Self-Test),缩写为POST,如果硬件出现问题,主板会发出不同含义的蜂鸣,启动中止。如果没有问题,屏幕就会显示出 CPU、内存、硬盘等信息
¶启动顺序选择
硬件自检完成后,BIOS 把控制权转交给下一阶段的启动程序。此时,BIOS 需要知道,下一阶段的启动程序具体存放在哪一个设备之上。也就是说,BIOS 需要有一个外部储存设备的排序,排在前面的设备就是优先转交控制权的设备。这种排序叫做启动顺序(Boot Sequence)
¶第二阶段:主引导记录(MBR)
BIOS 按照「启动顺序」,把控制权转交给排在第一位的储存设备。这时,计算机读取该设备的第一个扇区,也就是读取最前面的 512 个字节。如果这 512 个字节的最后两个字节是 0x55 和 0xAA,表明这个设备可以用于启动;如果不是,表明设备不能用于启动,控制权转交给启动顺序中的下一个设备
¶主引导记录的结构
MBR 由于只有 512 字节,放不了太多信息,它的主要作用是:告诉计算机硬盘的哪一个位置存放着操作系统
✨MBR 由三部分组成
¶分区表
磁盘分区有很多好处,考虑到每个区可以安装不同的操作系统,MBR 因此必须知道将控制权交给哪个区。分区表的长度只有 64 个字节,里面又分成四项,每项 16 个 字节。所以,一个硬盘最多只能分四个一级分区,又叫做主分区
✨每个主分区的 16 字节,由以下 6 部分组成
如果每个扇区为 512 个字节,就意味着单个分区最大不超过 2 TB。再考虑到扇区的逻辑地址也是 32 位,所以单个硬盘可利用的空间最大也不超过 2TB。如果想使用更大的硬盘,只有 2 个方法:一是提高每个扇区的字节数,二是增加扇区总数
¶第三阶段:磁盘启动(Grub)
此时,计算机的控制权转交给硬盘的某个分区,此时又分成三种情况
¶情况一:卷引导记录
四个主分区里面,只有一个是激活的。计算机会读取激活分区的第一个扇区,叫做卷引导记录(Volume Boot Record,VBR)
¶情况二:扩展分区和逻辑分区
随着硬盘越来越大,四个主分区已经不够了,需要更多的分区。但是,分区表只有四项,因此规定有且仅有一个区可以被定义成扩展分区(Extended Partition),所谓扩展分区,就是指这个区里面又分成多个区。这种分区里面的分区,就叫做逻辑分区(logical partition)。
计算机先读取扩展分区的第一个扇区,称为扩展引导记录(Extended Boot Record,EBR),它里面也包含一张 64 字节的分区表,但是最多只有两项(也就是两个逻辑分区)
¶情况三:启动管理器
在这种情况下,计算机读取主引导记录前面 446 字节的机器码之后,不再把控制权转交给某一个分区,而是运行事先安装的启动管理器(Boot Loader),由用户选择启动哪一个操作系统。Linux 环境中,目前最流行的启动管理器是Grub
¶第四阶段:操作系统启动
控制权转交给操作系统后,操作系统的内核首先被载入内存。
具体的操作系统启动流程在下面由阐述
¶Linux(操作系统) 启动
计算机的启动最后一步,就是操作系统的启动,接下来将研究操作系统的启动流程
¶第一步:加载内核
操作系统接管硬件以后,首先读入 /boot 目录下的内核文件
1 | ls /boot |
¶第二步:启动初始化进程
内核文件加载以后,就开始运行第一个程序 /sbin/init,它的作用是初始化系统环境,由于 init 是第一个运行的程序,它的进程编号(pid)就是 1。其他所有进程都从它衍生,都是它的子进程
¶第三步:确定运行级别
许多程序需要开机启动。它们在 Windows 叫做「服务」(service),在 Linux 就叫做守护进程(Daemon)。
🎶也就是说,启动时根据运行级别,确定要运行哪些程序
✨Linux 预置七种运行级别(0-6)。一般来说,0 是关机,1 是单用户模式(也就是维护模式),6 是重启。运行级别 2-5,各个发行版不太一样,对于 Debian 来说,都是同样的多用户模式(也就是正常模式)
init 进程首先读取文件 /etc/inittab
,它是运行级别的设置文件。如果你打开它,可以看到第一行是这样的:
1 | id:2:initdefault: |
initdefault 的值是 2,表明系统启动时的运行级别为 2。如果需要指定其他级别,可以手动修改这个值
🤔那么,运行级别 2 有些什么程序呢,系统怎么知道每个级别应该加载哪些程序呢?
✨运行程序命名与运行特点
这个目录里的所有文件(除了 README ),是启动时要加载的程序。如果想增加或删除某些程序,不建议手动修改 /etc/rcN.d 目录,最好是用一些专门命令进行管理
¶第四步:加载开机启动程序
七种预设的运行级别各自有一个目录,存放需要开机启动的程序
😣如果多个运行级别需要启动同一个程序,那么这个程序的启动脚本,就会在每个目录都有一个拷贝,这样必然会造成管理上的困扰,如何做到优雅的修改启动脚本?
1 | $ ls -l /etc/rc2.d |
¶第五步:用户登录
开机启动程序加载完毕以后,就要让用户登录了
✨一般而言,用户的登录方式有三种(命令行登录、SSH 登陆和图形界面登陆),不同的登录方式存在各自验证用户身份的方式
¶命令行登录
¶ssh 登录
¶图形界面登录
¶第六步:进入login shell
所谓 shell,简单说就是命令行界面,让用户可以直接与操作系统对话,其中用户登录时打开的 shell,就叫做 login shell
¶命令行登录 & ssh 登录
首先读入 /etc/profile
,这是对所有用户都有效的配置;然后依次寻找下面三个文件,这是当前用户对bash
的配置
1 | ~/.bash_profile |
¶图形界面登录
¶第七步:打开non-login shell
完成上一步,Linux 的启动过程已经结束,用户已经可以看到命令行提示符或者图形界面了,但是,为了内容的完整,必须再介绍一下这一步。用户进入操作系统以后,常常会再手动开启一个 shell。这个 shell 就叫做 non-login shell
,意思是它不同于登录时出现的那个 shell,不读取 /etc/profile
和 .profile
等配置文件
✨只要运行 ~/.profile 文件,~/.bashrc 文件就会连带运行
1 | #~/.profile文件中的一部分代码 |
🤔为什么 bash 的设置这么繁琐?不能和 Spring 一样统一配置,统一启动?
¶系统运行级别
¶Centos6
系统一共有七个运行级别
使用runlevel
命令查看运行级别,使用init
命令调整运行级别
通过修改 /etc/inittab
可以做到永久性更改启动级别
00:系统的关机级别 init 1 进入到关机状态
01:用户的单用户模式 用于修复系统 或重置密码信息,
02: 系统的多用户模式, 没有网络
03: 系统的多用户模式 正常系统运行多用户模式级别 有网络
04:预留级别
05: 图形化界面
06: 系统的重新启动级别
¶Centos7 运行目标(target)
/usr/lib/systemd/system/runlevel*target
1 | systemctl get-default |
0(poweroff target):系统的关机级别 init 1 进入到维修模式
1(rescue target):用户的单用户模式 用于修复系统 或重置密码信息,
2(multi-user target): 系统的多用户模式, 没有网络
3(multi-user target): 系统的多用户模式 正常系统运行多用户模式级别 有网络
04(multi-user target):预留级别
05(graphical target): 图形化界面
06(reboot target): 系统的重新启动级别
¶附录
计算机是如何启动的?
Linux 的启动流程——阮一峰
开机流程、模组管理与 Loader——鸟哥
开机流程管理——鸟哥
Linux 开机详细流程——骏马金龙