原文标题:How Computers Boot Up

原文地址:http://duartes.org/gustavo/blog/

[注:本人水平有限,只好挑一些国外高手的精彩文章翻译一下。一来自己复习,二来与大家分享。]

前一篇文章介绍了Intel计算机的主板与内存映射,从而为本文设定了一个系统引导阶段的场景。引导(Booting)是一个复杂的,充满技巧的,涉及多个阶段,又十分有趣的过程。下图列出了此过程的概要:

引导过程概要

当 你按下计算机的电源键后(现在别按!),机器就开始运转了。一旦主板上电,它就会初始化自身的固件(firmware)——芯片组和其他零零碎碎的东西 ——并尝试启动CPU。如果此时出了什么问题(比如CPU坏了或根本没装),那么很可能出现的情况是电脑没有任何动静,除了风扇在转。一些主板会在CPU 故障或缺失时发出鸣音提示,但以我的经验,此时大多数机器都会处于僵死状态。一些USB或其他设备也可能导致机器启动时僵死。对于那些以前工作正常,突然 出现这种症状的电脑,一个可能的解决办法是拔除所有不必要的设备。你也可以一次只断开一个设备,从而发现哪个是罪魁祸首。

如果一切正常,CPU就开始运行了。在一个多处理器或多核处理器的系统中,会有一个CPU被动态的指派为引导处理器(bootstrap processor简写BSP),用于执行全部的BIOS和内核初始化代码。其余的处理器,此时被称为应用处理器(application processor简写AP),一直保持停机状态直到内核明确激活他们为止。虽然Intel CPU经历了很多年的发展,但他们一直保持着完全的向后兼容性,所以现代的CPU可以表现得跟原先1978年的Intel 8086完全一样。其实,当CPU上电后,它就是这么做的。在这个基本的上电过程中,处理器工作于实模式分页功能是无效的。此时的系统环境,就像古老的MS-DOS一样,只有1MB内存可以寻址,任何代码都可以读写任何地址的内存,这里没有保护或特权级的概念。

CPU上电后,大部分寄存器的都具有定义良好的初始值,包括指令指针寄存器(EIP),它记录了下一条即将被CPU执行的指令所在的内存地址。尽管此时的Intel CPU还只能寻址1MB的内存,但凭借一个奇特的技巧,一个隐藏的基地址(其实就是个偏移量)会与EIP相加,其结果指向第一条将被执行的指令所处的地址0xFFFFFFF0(长16字节,在4GB内存空间的尾部,远高于1MB)。这个特殊的地址叫做复位向量(reset vector),而且是现代Intel CPU的标准。

主板保证在复位向量处的指令是一个跳转,而且是跳转到BIOS执行入口点所在的内存映射地址。这个跳转会顺带清除那个隐藏的、上电时的基地址。感谢芯片组提供的内存映射功能,此时的内存地址存放着CPU初始化所需的真正内容。这些内容全部是从包含有BIOS的闪存映射过来的,而此时的RAM模块还只有随机的垃圾数据。下面的图例列出了相关的内存区域:

引导时的重要内存区域

随后,CPU开始执行BIOS的代码,初始化机器中的一些硬件。之后BIOS开始执行上电自检过程(POST),检测计算机中的各种组件。如果找不到一个可用的显卡,POST就会失败,导致BIOS进入停机状态并发出鸣音提示(因为此时无法在屏幕上输出提示信息)。如果显卡正常,那么电脑看起来就真的运转起来了:显示一个制造商定制的商标,开始内存自检,天使们大声的吹响号角。另有一些POST失败的情况,比如缺少键盘,会导致停机,屏幕上显示出错信息。其实POST即是检测又是初始化,还要枚举出所有PCI设备的资源——中断,内存范围,I/O端口。现代的BIOS会遵循高级配置与电源接口(ACPI)协议,创建一些用于描述设备的数据表,这些表格将来会被操作系统内核用到。

POST完毕后,BIOS就准备引导操作系统了,它必须存在于某个地方:硬盘,光驱,软盘等。BIOS搜索引导设备的实际顺序是用户可定制的。如果找不到合适的引导设备,BIOS会显示出错信息并停机,比如"Non-System Disk or Disk Error"没有系统盘或驱动器故障。一个坏了的硬盘可能导致此症状。幸运的是,在这篇文章中,BIOS成功的找到了一个可以正常引导的驱动器。

现在,BIOS会读取硬盘的第一个扇区(0扇区),内含512个字节。这些数据叫做主引导记录(Master Boot Record简称MBR)。一般说来,它包含两个极其重要的部分:一个是位于MBR开头的操作系统相关的引导程序,另一个是紧跟其后的磁盘分区表。BIOS 丝毫不关心这些事情:它只是简单的加载MBR的内容到内存地址0x7C00处,并跳转到此处开始执行,不管MBR里的代码是什么。

主引导记录

这段在MBR内的特殊代码可能是Windows 引导装载程序,Linux 引导装载程序(比如LILO或GRUB),甚至可能是病毒。与此不同,分区表则是标准化的:它是一个64字节的区块,包含4个16字节的记录项,描述磁盘是如何被分割的(所以你可以在一个磁盘上安装多个操作系统或拥有多个独立的卷)。传统上,Microsoft的MBR代码会查看分区表,找到一个(唯一的)标记为活动(active)的分区,加载那个分区的引导扇区(boot sector),并执行其中的代码。引导扇区是一个分区的第一个扇区,而不是整个磁盘的第一个扇区。如果此时出了什么问题,你可能会收到如下错误信息:"Invalid Partition Table"无效分区表或"Missing Operating System"操作系统缺失。这条信息不是来自BIOS的,而是由从磁盘加载的MBR程序所给出的。因此这些信息依赖于MBR的内容。

随着时间的推移,引导装载过程已经发展得越来越复杂,越来越灵活。Linux的引导装载程序Lilo和GRUB可以处理很多种类的操作系统,文件系统,以及引导配置信息。他们的MBR代码不再需要效仿上述"从活动分区来引导"的方法。但是从功能上讲,这个过程大致如下:

1、  MBR本身包含有第一阶段的引导装载程序。GRUB称之为阶段一。

2、  由于MBR很小,其中的代码仅仅用于从磁盘加载另一个含有额外的引导代码的扇区。此扇区可能是某个分区的引导扇区,但也可能是一个被硬编码到MBR中的扇区位置。

3、  MBR配合第2步所加载的代码去读取一个文件,其中包含了下一阶段所需的引导程序。这在GRUB中是"阶段二"引导程序,在Windows Server中是C:/NTLDR。如果第2步失败了,在Windows中你会收到错误信息,比如"NTLDR is missing"NTLDR缺失。阶段二的代码进一步读取一个引导配置文件(比如在GRUB中是grub.conf,在Windows中是boot.ini)。之后要么给用户显示一些引导选项,要么直接去引导系统。

4、  此时,引导装载程序需要启动操作系统核心。它必须拥有足够的关于文件系统的信息,以便从引导分区中读取内核。在Linux中,这意味着读取一个名字类似"vmlinuz-2.6.22-14-server"的含有内核镜像的文件,将之加载到内存并跳转去执行内核引导代码。在Windows Server 2003中,一部份内核启动代码是与内核镜像本身分离的,事实上是嵌入到了NTLDR当中。在完成一些初始化工作以后,NTDLR从"c:/Windows/System32/ntoskrnl.exe"文件加载内核镜像,就像GRUB所做的那样,跳转到内核的入口点去执行。

这里还有一个复杂的地方值得一提(这也是我说引导富于技巧性的原因)。当前Linux内核的镜像就算被压缩了,在实模式下,也没法塞进640KB的可用RAM里。我的vanilla Ubuntu内核压缩后有1.7MB。然而,引导装载程序必须运行于实模式,以便调用BIOS代码去读取磁盘,所以此时内核肯定是没法用的。解决之道是使用一种倍受推崇的"虚模式"。它并非一个真正的处理器运行模式(希望Intel的工程师允许我以此作乐),而是一个特殊技巧。程序不断的在实模式和保护模式之间切换,以便访问高于1MB的内存同时还能使用BIOS。如果你阅读了GRUB的源代码,你就会发现这些切换到处都是(看看stage2/目录下的程序,对real_to_prot 和 prot_to_real函数的调用)。在这个棘手的过程结束时,装载程序终于千方百计的把整个内核都塞到内存里了,但在这后,处理器仍保持在实模式运行。

至此,我们来到了从"引导装载"跳转到"早期的内核初始化"的时刻,就像第一张图中所指示的那样。在系统做完热身运动后,内核会展开并让系统开始运转。下一篇文章将带大家一步步深入Linux内核的初始化过程,读者还可以参考Linux Cross reference的资源。我没办法对Windows也这么做,但我会把要点指出来。

参考:

http://blog.csdn.net/drshenlei/article/details/4250306

How Computers Boot Up.计算机的引导过程的更多相关文章

  1. The Kernel Boot Process.内核引导过程

    原文标题:The Kernel Boot Process 原文地址:http://duartes.org/gustavo/blog/ [注:本人水平有限,只好挑一些国外高手的精彩文章翻译一下.一来自己 ...

  2. Linux 引导过程内幕

    转载:http://www.ibm.com/developerworks/cn/linux/l-linuxboot/index.html   从主引导记录到第一个用户空间应用程序的指导 引导 Linu ...

  3. Linux学习笔记之Linux启动引导过程

    早期时,启动一台计算机意味着要给计算机喂一条包含引导程序的纸带,或者手工使用前端面板地址/数据/控制开关来加载引导程序.尽管目前的计算机已经装备了很多工具来简化引导过程,但是这一切并没有对整个过程进行 ...

  4. Linux引导过程

    早期时,启动一台计算机意味着要给计算机喂一条包含引导程序的纸带,或者手工使用前端面板地址/数据/控制开关来加载引导程序.尽管目前的计算机已经装备了很多工具来简化引导过程,但是这一切并没有对整个过程进行 ...

  5. Linux学习笔记:系统启动引导过程

    Linux系统启动引导过程 近期发现自己在仅仅是掌握上有几个比較硬的伤: 一.知识体系碎片,比方Linux,这学点那学点,结果没有成体系,串不起来: 二.记忆时间短暂,非常多的内容学了就忘,最后的结果 ...

  6. 【转】Linux 高级的视角来查看Linux引导过程

    [原文]https://www.toutiao.com/i6594210975480545800/ 1.概述 图 1 是我们在20,000 英尺的高度看到的视图. 当系统首次引导时,或系统被重置时,处 ...

  7. CFE Bootloader详解 — 引导过程

    CFE命令 CFE引导过程 系统加电后,CFE从boot.S (src/shared/boot.S)开始执行,完成判断芯片类型.设置时钟.初始化缓存.把自身加载进RAM等任务后,跳转到c_main() ...

  8. Linux系统引导过程及排除启动故障

    一.Linux操作系统引导过程二.系统初始化进程1.init进程2.Systemd3.Systemd单元类型三.排除启动类故障[1].修复MBR扇区故障(含实验过程)[2].修复GRUB引导故障●方法 ...

  9. Linux引导过程和服务过程

    目录 一.Linux操作系统引导过程 1.1.开机自检 1.2.MBR引导 1.3.GRUB菜单 1.4.加载Linux内核 1.5.init进程初始化 二.系统初始化进程 2.1.init进程 2. ...

随机推荐

  1. web 对接 platform

    一个项目拆成web和platform,web不对接数据库,只调用各个platform,每个平台负责出一个httpclient的client-jar包,封装好curd方法给web端调用,入参和出参用ja ...

  2. Centos6 rpm 安装mysql5.5(转)

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/macfac/article/details/51868712 0. 到官网下载好,想要安装的rpm包 ...

  3. [转]TA-Lib 安装

    转自:https://mrjbq7.github.io/ta-lib/install.html Installation You can install from PyPI: $ pip instal ...

  4. Consul+upsync+Nginx实现动态负载均衡 摘自https://blog.csdn.net/qq_29247945/article/details/80787014

    传统感念:每次修改完nginx配置文件,要重启nginx 动态感念:每次修改完nginx配置信息,不需要重启,nginx实时读取配置信息. Nginx: 反向代理和负载均衡 Consul:是用go编写 ...

  5. python 中变量引用问题

    普通变量,如a=10,str="fdaf",它们在函数内的值是不会被带到函数外的,除非在函数内加上global,而引用是惰性原则,从最近的同名父级同名变量引用值 其它变量如列表,字 ...

  6. ubuntu-docker入门到放弃(四)容器的导入导出

    上一次我们讲了如何搭建自己私有的镜像管理仓库,实际上我们使用的依然是别人或者公共的image,今天就来说说如何将自己定制化的images上传到自己的私有仓库中,以供符合自己业务场景的项目来使用,如:我 ...

  7. VC禁止或允许拖拽改变窗口尺寸

    创建窗口时用WS_THICKFRAME控制 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CMDIFrameWndEx:: ...

  8. JGit与远程仓库链接使用的两种验证方式(ssh和https)

    JGit是使用JAVA的API来操控Git仓库的库,由Eclipse公司维护.他提供的API分成两个层次,底层命令和高层命令.底层API是直接作用于低级的仓库对象,高层的API是一个面向普通用户级别功 ...

  9. pyqt信号和槽传递额外参数

    转载:fengyu09 环境:python2.7.8 —— pyqt 4.11.1 使用Pyqt编程过程中,经常会遇到给槽函数传递额外参数的情况.但是信号-槽机制只是指定信号如何连接到槽,信号定义的参 ...

  10. Ubuntu 14.10 下SSH配置

    安装Hadoop时候需要设置SSH ,故将此过程记录下来   推荐安装 OpenSSH , Hadoop 需要通过 SSH 来启动 Slave 列表中各台主机的守护进程,因此 SSH 是必需安装的.虽 ...