计算机是如何启动的?从未上电到操作系统启动

计算机是如何启动的,网络上很多博文1都从 BIOS 程序的加载开始说起,有的也跳到 BIOS 程序加载 Bootloader 阶段。个人认为把这个过程称为操作系统是如何被加载并启动应该更加贴切一点。同时,也有计算机硬件大神的文章[1][5]详细分析计算机加电的过程。在阅读前人的优秀文章之后,归纳总结写下了这篇文章以梳理从计算机上电之前到操作系统开始工作的整个过程。

开机键按下之前:黑暗中的一点星光
“滴答…滴答…”微弱的声音有规律地响起。

“是谁?”从睡梦中醒来,身边漆黑一片,我惊呼出声。

“哇,终于有朋友过来陪我玩了。你好你好,我是 RTC (Real-Time Clock,实时时钟)芯片,你可以叫我小 R,计算机世界的时间由我掌控哦,厉害吧~”,小R()得瑟地说。

我刚想说话,一个年迈爽朗的笑声传来,“哈哈,孩子,你又偷偷溜出来玩啦。”一位老爷爷走过来,慈祥地摸着小 R 的小脑袋说。

“家里太无聊了嘛,都没人可以陪我一起玩,没有"电",大家都不说话。对啦,这是我的电池爷爷,爷爷特别喜欢我,能让我一直活跃着呢!”

我一拍脑袋,感情这是来到了计算机的世界呀,而且还是没接入外部电源之前的计算机。在没有外部电源的情况下,基本只有 RTC 和 CMOS 在 RTC 电源供电的情况下才能正常工作。“电池爷爷”一般是个纽扣电池。RTC 芯片保持机器内部的时钟,这也是为什么我们的计算机关机之后再次启动时间还是准确的(不考虑操作系统启动后利用网络同步时间)。而 CMOS 是电脑主板上的一块可读写的RAM芯片。因为可读写的特性,所以在电脑主板上用来保存 BIOS 设置计算机硬件参数后的数据。在计算机领域,CMOS 常指保存计算机基本启动信息(如日期、时间、启动设置等)的芯片。

正回想着,突然天空一道光柱射向地面,后如溪流一般四处蔓延开来。“嘻嘻,有新朋友要醒来咯”,小 R 边跳边喊。“电池爷爷,您辛苦啦,回去休息吧,现在我能靠外面的能源生活啦。”

看来是外部的 ATX 电源接入了。ATX 会使用 +5VSB 电源唤醒一部分小伙伴,例如南桥(系统 I/O 芯片)、EC(嵌入式控制器,单片机)等。"+5V Stand-By 电压为开机电路和需要唤醒机器的WOL(Wake-up On Lan)和 USB 等设备提供电源”[7],不会为 CPU 等提供工作电压。

这里需要说明一下,实际上不同的主板、应用场景都会采用不同的电源时序控制方案,笔记本采用 EC,台式机很多用SIO(Super I/O)或者定制芯片,嵌入式设备以及手机采用PMIC(Power Management IC)。以上的故事都是基于台式机形式,但是我们选用 EC 来解释电源时序控制过程,是考虑到国内关于 EC 的资料较多。与台式机不同的一点是,笔记本因为有锂电池的原因,在没有接入电源适配器前,EC 以及南桥就已经处于工作状态了。这也是为什么我们打开笔记本电脑,按下开机键,系统能接收到这个信号,并准备开始工作。

讨论到这里,基本可以形成这样一个概念:在关机状态下,只有 RTC 、EC 以及南桥部分组件在工作。纽扣电池维持着计算机的时钟信息(RTC的工作)和 CMOS 信息,而 EC 则在等待用户按下开机键。当然 EC 还负责电池的充放电的检测,指示灯,功能键等功能。

黎明:计算机开始运转
主人说要有光,按下了神圣的开机键。EC 在黑暗中接收到这个PWRSW#信号,兴奋地不行,立马去通知南桥,“PM_PWRBTN#! PM_PWRBTN#! 我们的黎明到来啦!”。

“好啦,我知道!”,南桥回应 EC 三个信号SLP_S5#(退出 S5 关机状态),SLP_S4#(退出 S4 休眠状态),SLP_S3#(退出 S3 待机状态)。

“ATX 电源,赋予我们光明吧!”EC 收到南桥发来的信号后,明白南桥已经准备就绪。ATX电源收到信号,开始工作,发出各路基本电压给主板上的各个元件。然后发送PWROK#信号给 EC,并由 EC 转发给南桥与北桥…经过一系列你来我往(这个流程必须严格控制,任意一步出错都会造成计算机无法正常启动),终于等到通知 CPU 老大的时刻啦。

”嘿,北桥大哥,我们叫 CPU 老大醒来指挥我们吧。我会告诉 CPU 老大电源都准备就绪啦。“,南桥发送PLT_RST#给北桥,紧接着向 CPU 发送 PWRGOOD#信号。北桥接收到南桥的信号,默念一秒钟后,向 CPU 老大发送了CPU_RST#信号。

从此计算机世界开始热闹起来。

BIOS 现身
目前只是所有硬件开始工作,如果整个系统中没有指令存在,CPU 醒来也不知道该去做什么。计算机启动的英文表达是bootstrap,这来自于一句谚语:“pull oneself up by one’s bootstraps”,意思是”拽着自己的鞋带把自己拉起来“。

这当然是不可能的事情。最早的时候,工程师们用它来比喻,计算机启动是一个很矛盾的过程:必须先运行程序,然后计算机才能启动,但是计算机不启动就无法运行程序!早期真的是这样,必须想尽各种办法,把一小段程序装进内存,然后计算机才能正常运行[2]。
那么这就是BIOS(Basic Input/Output System,基本输入输出系统)阶段了。具体是如何工作的呢?

CPU 一醒来,毫不迟疑,立马开始工作。以Intel 32位 CPU 为例,CPU 知道自己的使命,第一步就是取地址0xFFFFFFF0[8]处的指令(CPU 设计时固化的功能,理解这个很重要)。CPU拿到指令后执行,发现这条指令是告知自己,下一次去另一个地址取指(跳转指令jmp [0xFFFF0000,0xE05B])。喔,想起来了,这是 BIOS 老弟等我去执行他保存的那一堆指令呢!CPU 又立马开始工作,通过 FSB(前端总线)将这个地址发送到北桥,然后通过 HUB-LINK 到南桥,通过LPC(Low Pin Count Bus)到 EC,再通过 X-BUS 一直到达 BIOS 取指令。在CPU读到所发出的地址内的指令后,开始 BIOS 程序执行。

BIOS 芯片中也保存了不少指令,形成的功能包括:

自诊断程序:读取 CMOS 中的内容获得硬件配置信息,并对其进行自检和初始化;完整的 POST(Power On Self Test) 自检将包括CPU、640K基本内存、1M以上的扩展内存、ROM、主板、 CMOS RAM、串并口、显示卡、软硬盘子系统及键盘测试。
CMOS 设置程序:引导过程中,用特殊热键启动,进行设置后,存入CMOS RAM中;对应 Dell 计算机启动时我们按F12,进入的 BIOS 设置界面。
系统自举装载程序:在自检成功后将磁盘相对 0 道 0 扇区上的引导程序装入内存,让其运行引导操作系统;
主要 I/O 设备的驱动程序和中断服务:系统硬件的变化由 BIOS 隐藏,程序使用 BIOS 功能而不是直接控制硬件。不过现代操作系统会忽略 BIOS 提供的抽象层并直接控制硬件组件。
操作系统引导:Bootloader
在前面提到,BIOS 会负责将磁盘相对 0 道 0 扇区的引导程序装入内存。不知道大家是否会有这样的疑问:为什么我们一定需要一个引导程序呢?为什么不能直接让 BIOS 将操作系统加载到内存中?

为了解答这个问题,首先要知道 Bootloader 都实现了什么功能。Bootloader 最直观的功能就是将操作系统加载到内存中。首先可以考虑在硬盘上存在多个操作系统的情况下,操作系统的加载方式过程可能就不同。如果让 BIOS 来考虑各个操作系统待加载到内存中的目的地址,这会导致 BIOS 程序的膨胀。而 BIOS 程序是固化在 BIOS 芯片中,正常情况下是无法修改的,解决加载新的操作系统出现问题就会很麻烦。而保证 BIOS 的正常功能就要降低 BOIS 的复杂性,那么适配不同操作系统的任务谁来做呢?那当然就是 bootloader 啦。并且在嵌入式环境下,操作系统的加载并不仅仅从磁盘上加载,还可能是Nor Flash 、NAND flash、USB 甚至是网络。那么 Bootloader 就应该实现基本的网络功能,例如著名的开源项目 U-Boot就是这样做的。当然本文在这里只是抛砖引玉,为什么要分出一个 Bootloader 层,可以从很多方面分析这样做的优势。

普通的 Bootloader 都需要实现什么功能呢:

初始化硬件设备
为操作系统准备RAM空间
将操作系统代码载入到RAM中
设置堆栈执行环境,为高级语言(如 C 语言)提供执行环境。这里要多说一句,操作系统并不都是 C 语言写的哦。现在 Rust 语言接近 C 语言性能,并且因为其提供的安全性,已经被用来写操作系统了。
将控制权交给操作系统。到这一步,系统的完整启动也就结束啦。之后就是操作系统主宰的世界了!
如果读者对 Bootloader 的详细工作工作过程感兴趣,可以参考 MIT6.828 操作系统课程 Lab1。这个实验引导学生一步一步 Coding 了操作系统的启动。读者若对操作系统的设计感兴趣,想详细了解这个课程,墙裂推荐!

一丁点儿:MIT6.828-神级OS课程-要是早遇到,我还会是这种 five 系列

最后,最近读了《码农翻身-用故事给技术加点料》这本书,用故事来讲技术知识。读的时候就觉得作者特别有趣有才,尤其在自己也尝试用故事来讲技术之后,发现真的不容易,直接五体投地的服!

这是我第一次尝试以拟人+故事的方式来写技术相关的文章,不喜轻喷(逃…

参考文献
[1]. 老狼. 按下开机键后,电脑都干了些什么? - 老狼的回答 - 知乎

[2]. 阮一峰. 计算机是如何启动的?

[3]. Iknow. 笔记本电源管理芯片(EC)作用的介绍

[4]. StackOverflow. Why do we need a bootloader in an embedded device?

[5]. 人生一次万般活法. 按下开机键后,电脑都干了些什么? - 人生一次万般活法的回答 - 知乎

[6]. W3Cschool BIOS完全手册. 什么是BIOS和COMS

[7]. 老狼. 电源是如何提供电力给主板的,又是如何切断的?

[8]. Intel Corporation. 英特尔® 64 位和 IA-32 架构开发人员手册:卷 3A


  1. 2 ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/531360.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hibernate注解

前言: 最近正在学习Hibernate通过注解(annotation)来管理映射关系,以前都是通过XML映射文件。下面拿个小例子说一下。 数据库物理模型: 数据库的描述: 一篇博客随笔可以分到不同的类中,一个类中…

js表单动态添加数据并提交

情景1&#xff1a;已经存在form对象了&#xff0c;动态为form增加对象并提交 function formAppendSubmit(){var myform$(#newArticleForm); //得到form对象var tmpInput$("<input typetext nameblogArticleForm.articleContent/>");tmpInput.attr("value&…

*++p和*p++的区别

首先你应该明白* 和 的优先级是相同的&#xff0c;而且他们的结合性是从又往左的 #include <stdio.h>int main(int argc ,char * argv[]) {int str[]{1,2,3,4,5,6,7,8,9,10};int *p str;int a *p;//a*p ,pp1即a1&#xff0c;p&str[1]int b *p;//pp1,b*p即p&s…

zyUpload+struct2完成文件上传

前言&#xff1a; 最近在写自己的博客网站&#xff0c;算是强化一下自己对s2sh框架的理解。期间遇到了很多问题&#xff0c;这些问题在写之前都考虑过&#xff0c;感觉也就是那样吧。但正真遇到了&#xff0c;也挺让人难受的。就利用zyUpload这个js插件实现文件的上传&#xff…

gbd的简单使用(一)

这篇文章将gdb的简单使用&#xff0c;通过此篇文章你能学习到使用gdb进行调试程序 在Linux中编写程序时&#xff0c;如何进行程序的debug工作呢&#xff1f;今天来介绍下gdb这个工具&#xff0c;可以在Linux下直接man gdb查看帮助信息 &#xff08;一&#xff09;gdb命令介绍 …

java发送内嵌图片邮件

前言&#xff1a; 博客系统中需要邮件服务的功能&#xff0c;以前写过类似的功能&#xff0c;不过功能太简单了&#xff0c;仅仅是发送文本内容&#xff0c;现在尝试一下发送内嵌图片邮件&#xff01; 准备工作&#xff1a; 请参考&#xff1a;http://www.cnblogs.com/hujunzhe…

调试跟踪利器---strace

通过这篇文章你会学习到strace的用法&#xff0c;strace可以帮助你高效地定位进程中的一些错误&#xff0c;关于strace的用处有很多&#xff0c;可以自行发掘 前面我们讲解了gdb调试程序,这篇文章介绍另一个调试跟踪工具strace&#xff0c;同样你可以在linux下执行man strace查…

MBR、DBR、FAT32基础小知识

MBR-------主引导记录 1.创建时间&#xff1a;由分区软件&#xff08;Fdisk/PartitionMagic/Windows 2000/Windows XP安装 工具等&#xff09;给 硬盘分区时建立的。 2.功能 &#xff1a;存放硬盘分区信息和引导系统时检查分区。 3.作用范围&#xff1a;MBR和虚拟MBR控制着整个…

java使用Executor(执行器)管理线程

一.一个实现了Runnable接口的类 class MyThread implements Runnable{private static int num 0;Overridepublic void run() {while(true){synchronized(MyThread.class){num;try{Thread.sleep(500);} catch(Exception e){System.out.println(e.toString());}System.out.print…

JMM和happens-before原则

JMM&#xff1a; Java Memory Model(Java内存模型)&#xff0c;围绕着在并发过程中如何处理可见性、原子性、有序性这三个特性而建立的模型。 可见性&#xff1a; JMM提供了volatile变量定义、final、synchronized块来保证可见性。  例如&#xff1a;线程a在将共享变量x1写入…

SD卡移植FAT32文件系统无MBR

问题&#xff1a;在研究SD卡和FAT32文件系统的时候&#xff0c;发现SD卡有的有MBR&#xff0c;有的没有MBR&#xff0c;这个为什么呢&#xff1f; 分析&#xff1a;MBR是主引导记录&#xff0c;是在给磁盘分区的时候建立的&#xff0c;我们的SD卡没有这个可能就是没有进行过分区…

java获取类的信息

关键技术剖析 1.java.lang.reflect包实现了java的反射机制&#xff0c;在使用反射机制时&#xff0c;需要导入该包。 2.Class类的forName方法能够根据类名加载类&#xff0c;获得类的Class对象。 Class类的getSuperclass方法获得父类的Class对象&#xff1b;getDeclaredFields方…

FAT32文件系统介绍

FAT32文件系统&#xff08;一&#xff09;为什么要有文件系统&#xff08;二&#xff09;FAT32文件系统组成&#xff08;三&#xff09;分步介绍各部分(1) 首先介绍一下MBR(2)DBR介绍(3)FAT表介绍(4) 数据区&#xff08;一&#xff09;为什么要有文件系统 文件系统是操作系统用…

java中动态代理实现机制

前言&#xff1a; 代理模式是常用的java设计模式&#xff0c;它的特征是代理类与委托类有同样的接口&#xff0c;代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类&#xff0c;以及事后处理消息等。代理类与委托类之间通常会存在关联关系&#xff0c;一个代理类…

libiconv库简单裁剪支持CP437编码

有许多人在做项目的时候都会遇到字符编码的不一致导致的乱码问题&#xff0c;那如何去解决呢&#xff1f;在Linux系统上可以通过iconv函数族来进行编码转换&#xff0c;但有时候我们并不需要全部的字符集&#xff0c;因为可能会占用比较大的空间&#xff0c;本文主要支持CP437编…

简单java在线测评程序

简单java程序在线测评程序 一&#xff0e;前言 大家过年好&#xff01;今年的第一篇博客啊&#xff01;家里没有网&#xff0c;到处蹭无线&#xff01;日子过得真纠结&#xff01;因为毕设的需求&#xff0c;简单写了一个java程序在线测评程序&#xff0c;当然也可以在本地测试…

指针强制类型转换触发内存自动对齐

C语言的指针是我们操作很灵活&#xff0c;但是也留下了不少坑&#xff0c;今天工作遇到了一个指针的坑&#xff0c;这里复现一下&#xff1a; 指针类型强制转换,并进行解引用,引起的内存对齐问题.&#xff08;一&#xff09;问题复现&#xff1a; 运行环境&#xff1a;Ubuntu …

简单文本编辑器

一、前言 聚天地之灵气&#xff0c;集日月之精华&#xff01;一个简单的java文本编辑器由此而生。毕设所需&#xff0c;很是无奈&#xff01; 二、界面预览 三、实现思路 1.字体选择器的实现 (1).字体类 class MyFont{private Font font;private Color color;public Font getFo…

u-boot新增命令后出现data abort

&#xff08;一&#xff09;问题描述 u-boot下新增了一条update的命令&#xff0c;直接输入update没有报错&#xff0c;但是输入up按TAB键补全时发现出现data abort&#xff0c;而且输入不支持的命令也会有data abort &#xff08;二&#xff09;解决方法 最开始我包含的头…

sublime text学习

Ctrl / ---------------------注释 Ctrl 滚动 --------------字体变大/缩小 Ctrl N-------------------新建 软件右下角可以选择文档语法模式 Ctrl Shift P ------------------命令模式 命令&#xff1a; sshtml模糊匹配-----语法切换到html模式&#xff0c;同理所得&am…