操作系统之旅 - 引导你的操作系统(一)

再说几句废话

话说作为一个非专业人士,我写写代码也只是满足一下自己的好奇心,费了很大的劲儿写出来的东西也就自己看看。一旦觉得有什么不好的,亦或是有什么新的想法,就立刻动手改。甚至重写也不觉得有一点点可惜。整个项目就是自己整着玩儿,用专业的话来说,整个项目也没有什么里程碑。就这样兜兜转转,我居然将Views重写了两遍。直到目前,整个项目还在不断的修改、前进中。

整个过程中,真正的感悟是:原来感觉神秘的操作系统知识,书本上那些晦涩的概念,亲自动手试过后,便有透彻的理解,再也不会感觉困难了。虽然我并没有从事一份程序员的职位,但通过写Views让我对技术不再惧怕。在现实世界中,企业对技术到底是买还是自研总有无法避免的争论。特别是我从事的夕阳行业中的朝阳方向,当你有了这样一份“深入钻研”的经历后,在这种争论面前就会微微一笑,对自己的行业有更多的展望。

关于我从事的行业,未来有机会我想再开个专栏在仔细说说吧。废话讲的太多了,让我们回到Views,让我娓娓道来~ 

(下面开始的阐述都是我对x86系统及OS的理解,很多东西都是自己悟出来的,不免存在谬误,请各位轻拍)

引导你的操作系统

按照经典理论及网上的很多操作系统教学,你需要准备一张软盘。用汇编语言写一个512字节的“引导程序”,通过该引导程序再读取软盘后续的连续扇区,这些扇区中可能保存这你的OS的“内核”(Kernel)。我地第一版系统也是这么写的。通过经典的BIOS int13h调用(ah=2)可以读取软盘中的“绝对扇区”。此外还需要注意程序要定位到07c0:9000位置,才能运行。

这种做法会给你极大的满足感。仿佛不用花多少时间,就能在”裸机“上运行一段程序。我也曾经迷恋过。但这并没有什么好处,反而会给你后续调试带来诸多麻烦。每次需要运行时,你需要把512字节的引导程序和”内核”写入磁盘上指定的区域(因为引导程序容量太小,无法分析FAT12格式来加载内核文件),否则加载很容易失败。

看到这儿你可能已经晕乎了。没关系,其实,在后来的版本中,我尝试了一种直接在DOS中加载内核的方法。MS-DOS能支持文件的随意读取,因此从磁盘上正确地加载一个内核文件就是一件非常容易的事情。但...,DOS是什么...,这又是怎么一回事情呢?说到这儿,故事要从Intel x86架构开始说起啦。

“实模式”与“保护模式”

Intel自从制造内存芯片竞争不过日本人(这又是另一个有趣的故事了,很好地诠释了企业“战略”,有机会我们可以再开贴聊聊)后,就开始发力PC处理器芯片的研发。1978年,Intel发布了8086处理器。该处理器的发布初步奠定了Intel在PC处理器领域的地位。这个8086是16位的处理器,在当时可是相当先进的存在。8086可是大名鼎鼎的“x86架构”的始祖,你现在办公电脑上用的Intel芯片都还完全兼容8086的呢。

8086支持20位的地址线,理论上能访问1MB的内存。其中,384KB被系统保留(我们后面还会提到这块保留区域,敬请期待),软件真正能用的空间也就640KB。这就是著名的DOS只能使用640KB内存说法的由来。说到DOS,年轻的朋友们可能都没听说过。他的全名叫Disk Operation System,磁盘操作系统。是比尔盖茨发家致富的第一桶金。这是个简单的操作系统,主要就是让你能往磁盘上读写文件,并且完成“应用程序加载”的功能。这简单粗糙的东西,当年可是玩电脑必学的基础。当年要在电脑上玩“红警”游戏,就是通过这个DOS把游戏程序加载进来的。

DOS是个脆弱的系统,很容易就可以把它整崩了。这倒不仅仅是DOS的锅,而是当时的CPU很傻很天真,它不对需要执行的指令做很多的检查,就忠实地执行。一个无法无天的应用程序能把操作系统掀个底朝天,搞得不好CPU就一声不吭reset(重启)了。当然反过来说,也给了应用开发人员无穷无尽的空间。应用程序几乎能够访问到所有系统资源,甚至绕开操作系统直接操纵硬件。这在现在是难以想象的。一批想象力丰富的天才程序员们开发出了各种令人难以置信的程序。举个例子,在那个年代,应用程序都会劫持中断,在响应中断时做一些自己的事儿。大名鼎鼎的雷布斯同学,早年写得代码里面也用类似技巧:

各位看官,代码中的 oldInt2F_addr变量就是用来进行中断劫持的:-)

显而易见,在8086这种芯片上,是不可能开发出什么现代化的操作系统的。所以,看到过很多人批评DOS的文章,就我的理解而言,DOS是适应那个年代软硬件环境而出现的产物。比尔盖茨还是有观察力的,这DOS,就如维秘内衣秀的模特,多一份则肥,少一份则柴。在加上比尔盖茨母亲的“关系”,妥妥的成功,不是盖的。

我想,Intel也一定看到了这一点,指令执行前不进行检查,显然不行。甚至对一般的应用,应该锁定他们的权限,不让他们进行访问操作系统区域,改变中断等操作,保护整个系统。所以,在后续的80286,80386中,Intel引入了所谓的”保护模式“。在此模式下,操作系统具有访问系统一切资源的能力,但被严密地保护起来。而应用程序可访问资源被大大削弱。与之相对的,8086处理器上这么实诚的,允许应用程序为所欲为的模式,Intel把它成为”实模式“:-)。

”保护模式“可不仅仅只有强化保护那么简单。自从80386开始,Intel处理器已经升级到32位,能直接访问最大4GB的内存空间(当时这是令人恐怖的),且支持分页模式(未来我们会仔细讲),支持指令级的任务切换等。一大堆新功能令人眼花缭乱。这些新功能都只能在”保护模式“中才能使用。至于”实模式“吗,那就老老实实的兼容8086吧,向后兼容也是Intel制胜的法宝之一。

在这种”兼容“的思想下,8086之后的所有x86架构的芯片,在它上电的那一刻,是以”实模式“运行的。也就是说你办公用的电脑,在上电一瞬间,居然只是一块运行速度极快的8086... 操作系统将会在后续负责将CPU切换到”保护模式“,从而解锁所有高级的处理器能力。

寻址方式

我们知道,16位的处理器,实际上应当只能访问64KB的内存空间。那为什么8086能访问“多达1MB”的内存空间呢。原来,8086下的(实模式)将整个内存划分为很多个64KB的区段。要访问内存时,指定一个区段后,就可以访问连续的64KB内存。在经典教材中,我们称这个区段为“段”(Segment),用于访问连续64KB的16位地址称为基于“段”的偏移量(Offset)。在8086中,有好几个寄存器专门用来存放段的基底地址,Intel称他们叫“段寄存器”。当你需要访问内存时,将段地址装入一个段寄存器,再给出偏移量,即可进行1MB空间内的任意地址访问(实际情况更加复杂,以后用到后我们再来讲)。

对稍微近代一点的PC来说,1MB内存空间实在太小了。所以,要访问超过1MB空间,在保护模式中才能实现。在x86的32位保护模式下,段偏移量是一个32位的地址,因此每个段的最大长度为4GB。配合修改“段”寄存器,几乎可以访问无限的内存。这也是为什么所有现代的操作系统都启用了保护模式。

装入内核

在本篇的最后,我们简单讨论一下开头提到的问题:引导操作系统。引导的第一步是将内核装入内存。我们来讨论2个问题:1)内核装入到哪儿?2)如何装载内核。本篇将给出内核装入哪儿的我的理解,并卖个关子,谈谈装载内核的一些问题。下一篇我们来仔细讨论如何载入内核。

内核装入哪儿?

大家都已经知道了,处理器初始化后处于实模式。而实模式仅可以访问1MB内存。这个1MB空间还被分为两段,640KB的“常规内存”和384KB的“保留内存”区域。这就意味着内核的尺寸如果超过640KB,那么就必须拆分为2段,才能装入。这对于内核的开发,编译,链接都是个很大的问题。

所以,在我理解,内核装入1MB以上的内存区域才是合理的。有人可能会问,那么1MB以下的内存区域就浪费掉了?其实并没有,因为这些内存空间可作为空闲内存,被操作系统动态分配使用。此外,某些早期的硬件设备在进行DMA传送时要求分配的物理内存必须是低地址空间的内存,这时候,1MB以下的内存空间也就有了用武之地。我的Views就使用了这样的内存布局。有人可能还会问,那1MB以上空间不足以加载内核,怎么办。那我的回答是,这么小内存的电脑,扔掉算了:-)

如何装载内核?

早期的Linux的做法是将内核压缩后,通过一段装载程序将其装入实模式的1MB空间,然后将CPU切换成保护模式,将已经装载在内存中的压缩内核解压缩到1MB以上的内存空间,来完成内核的初步装载。大家就不免要问了,这不是脱裤子放屁,多此一举吗。为什么不先将CPU切换到保护模式,然后直接将内核装载到1MB以上的内存空间呢?

哈哈。这就要讲到大名鼎鼎的BIOS啦。大家知道,要从磁盘加载文件,你需要磁盘驱动程序,文件系统驱动程序等的支持。这些东西原本都是在内核里面实现的。但现在我们是要加载内核... 所以...,这些驱动都还不存在。好在有BIOS(Basic Input and Output System)。BIOS是固化的程序,提供对PC硬件的基本驱动能力,在没有操作系统的驱动程序的情况下,也可以对硬件(如磁盘)进行一些基本操作。但有一点,BIOS只能在实模式下运行。这就解释了Linux为什么必须要在实模式下装载内核的原因:在保护模式下,需要自行实现简易的设备驱动程序才能读取和加载内核。但这些驱动程序也是程序,也需要被加载。这就形成了一个死结。这么说,大家也就理解了,Linux在实模式下加载内核是不得已而为之的无奈之举了。

在下一篇中,我会来介绍一下Views是如何解决这个问题的。给个预告,我的思路是直接在实模式下将内核加载到1MB以上的内存空间里。听起来很神奇吧,让我们下篇在来好好聊聊。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值