热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[自制操作系统]第01回计算机启动过程

目录一、前言二、准备工作三、软件接力第一棒BIOS 一、前言我在学习操作系统的时候,看的是汤子瀛版的《计算机操作系统》第四版,这本书总的来说我觉得是写的还不错的,语言讲解通俗易懂。

目录

一、前言

二、准备工作

三、软件接力第一棒BIOS

 

一、前言

  我在学习操作系统的时候,看的是汤子瀛版的《计算机操作系统》第四版,这本书总的来说我觉得是写的还不错的,语言讲解通俗易懂。只不过看书终归是纸上谈兵,缺少实操的部分,就会导致自己以为懂得的知识点其实是经不起推敲的,无法清楚地复述出来的。所以后来我又查阅了一些其他的资料,其中郑钢的《操作系统真象还原》是我最喜欢的一本书,手把手教你写一个简单的操作系统,使我对之前书上的概念有了更加清晰的认识,本系列的所有文章是笔者在学习本书时的一些学习笔记,虽然这本书有一些小小的错误,但是瑕不掩瑜,依旧是我认为学习操作系统最好的一本书之一。此外,还要感谢博客园博主闪客,我在写这一个操作系统系列笔记时也大量参考了他的帖子,感兴趣的读者,我强烈推荐也去阅读一下他的帖子。

  回到正题,我为什么会想着写这么一个系列呢?其实我本人是喜欢做一些Linux嵌入式开发的工作的,以后也想从事这方面的工作,所以在日常学习中,难免就会与操作系统打一些交道。我不是科班出身的,因此需要自己补一下这方面的基础,所以也就有了这么一个系列的出现,写的不好,希望读者见谅,我只是把它当做自己学习的一个笔记,日后方便回来复习,不敢标称是什么教程。如果能帮助到别人那是我的幸运。对于帖子中出现的错误,我虚心接受读者的批评与指正。

二、准备工作

  本系列是基于Bochs平台编写基于x86架构的32位操作系统,所以我们有必要对x86架构有一个简单的认识。

  在1978年6月8日,Intel发布了新款16位微处理器“8086”,也同时开创了一个新时代:x86架构诞生了。x86指的是特定微处理器执行的一些计算机语言指令集,定义了芯片的基本使用规则。后来随着人们对性能需求的不断增长,Intel推出了越来越多性能更加强悍的处理器,如80286、80386、80486以及后面的奔腾系列等等。这些处理器有什么区别呢,我就只拿这三款处理器做一个简单的介绍。

   

  上图可以看到,CPU升级后,地址总线宽度和寄存器的宽度都相应地得到了提高,这样的好处便是CPU的运算速度较之从前有着明显的提高。

  可以看到里面有提到实模式,保护模式的概念,其实这个概念是人们后来为了区分CPU的运行模式人为加上去的。

  最初的x86架构的CPU是8086,它的所有寄存器都是16位的,只有地址线是20位,所以它访问空间的方式是段基址寄存器左移4位再加上段偏移地址,这样最终形成一个物理地址送上地址总线。这个寻址方式在我们现在看来有点奇怪,其实也是当时工程师提出的一种解决寄存器位数与地址总线宽度不匹配的方法。

  这有两个坏处,第一就是可访问的空间太小,跟不上计算机发展的需要。第二就是缺少保护机制,程序可以随意访问这 1M 的地址空间,甚至覆盖掉操作系统本身的代码和数据。

  这样操作系统的发展和需求,就倒逼着CPU的发展,于是有了80286,80286地址总线拓宽到了24位,拥有16MB的寻址空间,除此之外,80286通过对段选择子的方式对内存进行了保护,有了很多新的特性。但为了兼容老程序,必须还要支持16位机的特征,所以就有了两个模式,并且程序还要通过调用一些 CPU 的指令从一个模式切换到另一个模式,比如经典的打开A20地址线。

  80286虽然有了保护模式,但是依然是16位的CPU,其通用寄存器还是16位宽,即单独的一个寄存器还是只能访问64KB的空间,如果用寄存器作为段内偏移地址,段的大小还是64KB,要想访问完整的16MB内存,依然要不断地变换段基址,所以本质上和8086没有太大区别,也就导致80286比较鸡肋,很快就被淘汰了。后面80386出现了,32位地址线和32位寄存器直接一步到位解决问题,并且也支持保护模式。

  这两个模式,其实我们完全可以按照更准确的理解,叫做16位模式和32位模式,然后补充一句说32位模式比16位模式有了更大的寻址空间(这是自然的)和更好的内存保护机制。但由于CPU厂商希望凸显他们新模式的优势,所以直接把最关键的优势“保护”给放到了名字里,叫保护模式。而为了对比也要给之前的模式起一个名字,之前的模式比较实在,给出什么地址就直接是物理地址,也没有转换也没有安全保护,那就叫它实模式吧。

  现在我们只需要知道8086处理器是运行在实模式下的,而随着处理器的升级,后面的处理器可以运行在保护模式下,至于为什么80386一开始是运行在实模式下,后面再转换为保护模式呢,其实它也说到了,为了兼容,因为每一款产品必须兼容之前的设计,这样才会让顾客买单。

  对于Intel8086,我们可以看到它20条地址线,故可以访问到2^20=1048576=1MB的内存空间,若是按照十六进制来表示,则是0x00000~0xFFFFF。下面是实模式下的1MB内存布局。

   

  这里着重解释一个问题,也是以前我的一个认识的误区,我以前以为我们插在主板上的内存就是CPU眼中的内存,其实这个认识是错误的。首先我们知道地址总线宽度决定CPU可以访问的内存大小,如8086的地址总线是20位,那么可以访问的内存大小为1MB,80386的地址总线是32位,那么可以访问的内存大小为4GB。但是以上的地址范围是指地址总线可以触及到的边界,是指计算机在寻址上可以到达的疆域。并不是说寻址范围取决于内存条的大小,归根结底的原因是:在计算机中,并不是只有我们插在主板上的内存条需要通过地址总线来访问,还有一些外设同样是需要通过地址总线来访问的。所以,实际上CPU眼中的内存分布应该是这样的:

         

  关于其中提到的地址映射,这是在硬件层面完成的工作,对操作系统来讲是透明的。

三、软件接力第一棒BIOS

  我之前挺好奇每次一按主机上的电源键,电脑是怎么启动并运行的。所以我去百度了一下:当电源打开后,PC做的第一件事情就是CPU从内置的芯片中加载一个最简单程序,这个程序叫做BIOS(基本输入输出系统,随后BIOS程序启动后就会检测并初始化硬件设备,比如显卡,内存等,随后将控制权交给硬盘,在硬盘中寻找主引导记录的分区,这个分区告诉电脑操作系统在哪里,最后CPU从硬盘上加载操作系统完成启动过程。

  所以接下来的工作先从BIOS开始。

  BIOS全称叫做Base Input & Output System,即基本输入输出系统,它是被固化在计算机ROM芯片上的一组程序。它的主要工作是检测、初始化硬件。如何初始化的呢?这里说一下题外话,硬件厂商会事先实现这些初始化功能,最后在外部提供调用接口就行了,BIOS只需要通过这些调用接口就能完成硬件的初始化。BIOS还建立了中断向量表,这样CPU就可以通过“int 中断号”的方式来实现相关的硬件调用。

  在前面提到的实模式下的内存布局中,我们知道BIOS代码就存放在0xF0000~0xFFFFF。访问这个地址便是访问BIOS,那么BIOS代码是如何被执行的呢?换句话说就是CPU是如何知道BIOS代码存放于此的呢?其实这是事先通过硬件电路实现的,没错,就是这么魔幻。当上电后,CPU的cs:ip寄存器自动被赋值为0xf000:0xfff0,这个组合出来的地址便是0xffff0,这是处理器下一条待执行指令的地址。这个地址就是我们的BIOS代码的存放地址。这个地址存放的代码如下:

  jmp far f000:e05b

  这是一条跳转指令,cpu跳转到0xfe05b地址处执行,其实也在意料之中,因为在内存布局图中可以看到,0xffff0距离0xfffff也就只有16字节的空间,这么小的空间怎么能够完成BIOS的一系列初始化工作呢?

  所以跳转到0xfe05b才是BIOS真正开始执行的地方。接下来BIOS便开始马不停蹄地检测内存、显卡等外设的信息,当检测通过并初始化好硬件后,在内存中0x000~0x3FF处建立中断向量表IVT并且填写中断例程。至此,BIOS的使命也就结束了,我觉得没有必要去深究BIOS的代码。因为底层无非就是一些调用接口完成初始化的代码。

  虽然BIOS完成了它的使命,但是我们还需要继续走下去,这里提一句,BIOS最后会检查启动盘的第一个扇区中的内容,如果此扇区中末尾两个字节分别是魔数0x55和0xaa,那么BIOS便认为此扇区中存在可执行程序(也就是后面我们要讲解的主引导记录MBR),便将此扇区的内容全部加载到物理地址0x7c00处执行。

  关于为什么是检查第一个扇区、为什么是魔数0x55和0xaa以及为什么是地址0x7c00?

  这里我就借用一下书上的解释:第一个扇区和魔数的问题,其实就是为了方便,一个约定俗成的规定罢了;那为什么是地址0x7c00呢?其实是取决于当时操作系统本身所占的内存大小和内存布局罢了。也就是工程师们绞尽脑汁想要榨取每一块内存区域的利用价值导致最后遗留下的结果。这个区域也许现在看来有点奇怪或者不合适,但是为了系统兼容性问题,这个0x7c00的地址就一直沿用到现在。

  总结一下计算机的启动过程:



  1. 首先按下开机键后,CPU将cs:ip寄存器强制初始化为0xf000:0xfff0,这样得到的组合地址便是0xffff0,这个地址便是BIOS程序所在位置。

  2. BIOS程序所在位置是一条跳转指令,CPU跳转到地址0xfe05b处开始执行。

  3. 0xfe05b处才算是BIOS真正开始的地方,在此处的程序中BIOS完成硬件检测工作以及建立中断向量表后,将启动盘中的主引导记录加载到内存0x7c00处并跳转执行。

  4. 主引导记录中的代码主要是加载操作系统内核,并跳转到加载处执行。

  5. 最后操作系统便开始执行了,最终呈现在我们的面前的便是图形化的操作界面等等。

  现在我们已经知道BIOS将控制权递交给了MBR,那么接下来我们便开始动手写一个自己的MBR程序,欲知后事如何,请看下回分解。

 



推荐阅读
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • 嵌入式处理器的架构与内核发展历程
    本文主要介绍了嵌入式处理器的架构与内核发展历程,包括不同架构的指令集的变化,以及内核的流水线和结构。通过对ARM架构的分析,可以更好地理解嵌入式处理器的架构与内核的关系。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 众筹商城与传统商城的区别及php众筹网站的程序源码
    本文介绍了众筹商城与传统商城的区别,包括所售产品和玩法不同以及运营方式不同。同时还提到了php众筹网站的程序源码和方维众筹的安装和环境问题。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • RouterOS 5.16软路由安装图解教程
    本文介绍了如何安装RouterOS 5.16软路由系统,包括系统要求、安装步骤和登录方式。同时提供了详细的图解教程,方便读者进行操作。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 服务器上的操作系统有哪些,如何选择适合的操作系统?
    本文介绍了服务器上常见的操作系统,包括系统盘镜像、数据盘镜像和整机镜像的数量。同时,还介绍了共享镜像的限制和使用方法。此外,还提供了关于华为云服务的帮助中心,其中包括产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题和视频帮助等技术文档。对于裸金属服务器的远程登录,本文介绍了使用密钥对登录的方法,并提供了部分操作系统配置示例。最后,还提到了SUSE云耀云服务器的特点和快速搭建方法。 ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • 在2022年,随着信息化时代的发展,手机市场上出现了越来越多的机型选择。如何挑选一部适合自己的手机成为了许多人的困扰。本文提供了一些配置及性价比较高的手机推荐,并总结了选择手机时需要考虑的因素,如性能、屏幕素质、拍照水平、充电续航、颜值质感等。不同人的需求不同,因此在预算范围内找到适合自己的手机才是最重要的。通过本文的指南和技巧,希望能够帮助读者节省选购手机的时间。 ... [详细]
  • Apache Shiro 身份验证绕过漏洞 (CVE202011989) 详细解析及防范措施
    本文详细解析了Apache Shiro 身份验证绕过漏洞 (CVE202011989) 的原理和影响,并提供了相应的防范措施。Apache Shiro 是一个强大且易用的Java安全框架,常用于执行身份验证、授权、密码和会话管理。在Apache Shiro 1.5.3之前的版本中,与Spring控制器一起使用时,存在特制请求可能导致身份验证绕过的漏洞。本文还介绍了该漏洞的具体细节,并给出了防范该漏洞的建议措施。 ... [详细]
  • PG12新增的VACUUM命令的SKIP_LOCKED选项
    PG12版本的VACUUM命令新增了SKIP_LOCKED选项,该选项使得vacuum命令在遇到被lock住的table时可以跳过并被视为成功执行。之前的版本中,vacuum命令会一直处于等待状态。本文还提到了PostgreSQL 12.1版本的相关信息。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有