仍然是按照于渊《Orange'S 一个操作系统的实现》的线索进行,从第一章到第五章,进行一次总结,这样可以有效的理清最底层主要工作的脉络。这一部分也是汇编代码最为集中的部分,由于我对于汇编代码的调试很不熟悉,所以过程很是痛苦,还是需要继续习惯。
首先来看看从一个引导扇区到真正的内核,我们需要做什么工作:
引导扇区,作为我们的操作系统(目前来说的,也就是软盘启动的)首先读取并执行的一部分代码,它的装入和执行不需要我们的干预,但是它的致命缺陷就是:只有512字节(编译之后),这使得我们能实际在引导扇区中进行的工作非常少。实际上,在目前的学习中,引导扇区至少要提供一个引路的功能,通过引导扇区的执行将存在软盘(将来或许是硬盘)上的其他编译好的代码装入内存并执行。这样的话,被装入的可执行代码(称为Loader)没有512字节的限制,可以放心做我们想要做的事。
这个突破512字节的过程在书中第四章有集中的描述,我们发现在第四章作者花了大量的篇幅研究MS-DOS中软盘数据的组织和FAT12文件格式的细节,这是为什么呢?
从最简单的需求方面讲,我们只不过是需要从磁盘上找到Loader,然后把它装入内存而已,为啥这么麻烦呢?书中P117倒数第二段,作者对于这个问题给出了回答,试图使我们的代码和MS-DOS兼容是为了调试的方便。其实在我看来,这也是一种训练,毕竟以前的编程从来没有涉及到扇区读取或者文件系统这样的底层知识。通过这一部分的学习,至少对于相关的东西减少了恐惧感,今后肯定还要涉及FAT32、NTFS或者Ext3等各种各样的文件系统,但是有了研究过FAT12的经验,我相信任何文件系统都在我的能力范围之内了。
我在实际试验的时候,遇到了一个奇怪的问题,我测试软盘FAT12引导扇区格式的时候(参见书P104),分别使用了Virtual PC 5.2上的MS-DOS 6.22和Bochs上的FreeDos,结果发现FreeDos和MS-DOS对于软盘的文件系统组织是不太一样的。简单来讲,我在MS-DOS下的软盘根目录建立文件aaa和文件夹ppp,文件夹ppp中建立文件bbb。在MS-DOS下,一切如常。但是在FreeDos下,在A:/根目录执行dir会提示什么东西也没有,但是文件aaa
可以打开(我的aaa是一个文本文件,利用type aaa命令就可以查看了),接着我们cd ppp,可以进入A:/ppp/,在这里dir会显示原本是根目录的内容,也就是说,FreeDos在用dir命令时对于文件的识别和实际的情况差了“一层”。我目前不清楚这个情况产生的原因。
另外一个问题是,在书P104页的表中,我们可以看到BS_VolLab项表示的卷标,但是实际测试的结果是,无论是MS-DOS还是FreeDos都说“…… has no label”,原因不明。
好在以上的问题不影响我们的实际学习,我们只需要用MS-DOS 6.22就可以完成所有需要的工作(其实只是复制文件而已,囧)。
废话了半天,呃,我们的引导扇区要做的工作总结到一句话:引导扇区从软盘上找到Loader,将这个Loader装入内存并且把控制权移交。做起来也不难,一个扇区一个扇区找过去(当然是在固定的位置,比如说根目录下,这样简单),找到Loader.bin的话就把它复制到内存,最后一个jmp就好了。
Loader,顾名思义,Loader的作用是从软盘中找出kernel并且把它装入内存并且把控制权移交。呃……这句话很眼熟啊,和上一段的蓝色句子不是几乎一样的么……
事实上,如果引导扇区没有限制到512字节的话,我想Loader就不必出场了,Loader实际上是引导扇区的扩充,除了装入kernel,还要进行跳入保护模式和打开分页机制,为之后的kernel运行铺平道路。这些工作在512字节中完成基本上是不可能的,所以要用Loader完成。
以上部分主要是在书中第五章前半部分描述,可以发现作者又在详细叙述一种叫做ELF文件的东西,可怜的我之前完全没有听说过这样一种东西……
ELF的全称是Executable and Linking Format,按照我现在的理解,它是UNIX族OS下的一种二进制文件格式,它有些类似于WINDOWS下的exe(PE文件)。但是ELF文件不仅可以在装载器的帮助下运行,也可以作为动态链接库使用,还可以与汇编代码生成的目标文件连接(参见书5.2节)。
嗯,ELF之所以会在这里出现,主要的原因是我们基本上要结束“完全汇编”的时代了,后面到了内核部分,绝大多数代码将使用C语言完成(全部用汇编估计会疯掉……),但是不可避免的是混合C和汇编的编程(书第五章后半部分全部是这样的),所以我们要用ELF文件格式,这样可以简化工作(参见书5.2节,只要导出符号就可以了)。但是看看上面蓝色字体的Loader的作用,会发现这个装入并运行ELF文件的工作是有我们自己完成的,我们不能像在Linux下那样用./就去执行它,所以研究ELF文件的格式就是必须要完成的任务了。
总之,Loader在装入Kernel的时候稍微复杂一些,因为掺杂了ELF文件的处理。
Kernel,是真正的内核了,目前来说(到书第五章)内核还基本上没有什么实际的作用,只是作为一个样本,后面将着力扩充它。Kernel应该才是我们的操作系统真正的“业务逻辑”,前面说了那么多的引导扇区啦,Loader啦,全部是为了把控制权交给Kernel,真是够有派头……
接下来,大概叙述一下我们开发环境:
为了节省时间,我还是全部在WINDOWS下完成开发,主要的开发流程如下:
1、在NotePad++下完成源代码的编辑工作
2、启动cygwin,进行编译和连接,nasm、ld、gcc等等都可以方便使用。
3、用于渊《自己动手写操作系统(第一版)》附带的软盘引导扇区写入工具写入新的引导扇区到软盘映像(如果有更新的话,其实后来引导扇区基本不用管了)。
4、Virtual PC 5.2下启动MS-DOS 6.22,把第2步生成的文件(目前是.bin格式的,这个有64KB的大小限制,之后再改进)拷贝到软盘映像的预定位置(目前是根目录)。
5、Virtual PC 5.2下装入这个软盘映像,启动我们的操作系统,看是否有错,若有错,转第6步,否则开始下一阶段,转第1步。
6、Bochs下装入这个软盘映像,启动我们的操作系统并进行调试,找到bug后转第1步。
可以说,以上的开发过程是很笨拙的,之后我准备首先搞清楚make文件的写法,简化编译连接的步骤,另外就是如果全部在Linux下完成的话也许最快(熟练的情况下),可惜对我来说,这还需要时间。嘛,其实我是因为同时在windows下听听音乐啦(还要看歌词),下下东西啦,不得不说的是linux确实不太能胜任我的这些变态需求(笑),到开学就好了,没法下东西的时候就可以安心在Linux下好好学习天天向上了。
2009年8月8日9:58:35