由于,我们以后的操作系统要加载到软盘上,软盘的一种文件格式——FAT12。

可以想象,我们之前的程序局限在512字节的引导扇区,可是我们的操作系统会不断添加新功能,为了能够实现这个,我们就要不能局限在这第一个扇区(0,0,1),我们需要其他的扇区保存我们的程序,这些程序在运行前要加载到内存,然后才能执行。

于渊的书上有这样一句话:一个操作系统从开机到开始运行,大致经历“引导-->加载内核如内存-->跳入保护模式-->开始执行内核"这样一个过程。这样,作者提出了loader的概念,而loader就负责上述工作。让引导扇区负责把Loader加载入内存并且把控制权交给它,其他工作由Loader来做。

        杨文博的书是这样写的: 由于启动扇区512字节的大小限制,需要将程序保存在其他扇区,运行前加载到内存后,再跳转过去执行。但产生了问题:程序在软盘上应该怎样存储呢?

最直接的存储方式是顺序存储,即将一个大程序从启动扇区开始按顺序存储在相邻的扇区,可能这样需要的工作量小,在启动时操作系统仅仅需要序列地将可执行代码拷贝到内存中来继续执行。可是经过简单地思考我们就可以发现这样的缺陷:

       1.软盘中仅能存储操作系统程序,无法存储其他内容。

       2.我们必须使用二进制拷贝方式来制作软盘镜像,修改系统麻烦。

       这里,作者提出了文件系统,文件系统可以在一张软盘上存储不同的文件,并提供文件管理功能,可以让我们避免上述的两个缺点。在使用某种文件系统对软盘格式化之后,我们就可以像普通软盘一样使用它来存储多个文件和目录,为了使用软盘上的某个文件,这样突破启动扇区512字节大小的限制。

       看到这里,我突然明白了为什么要有文件系统这个东西,原来觉得只是一个储物柜,能存放各种东西,没想到原来是这样的原理。

       这里我们介绍FAT文件系统。它与其他文件系统一样,都将磁盘划分为层次进行管理。从逻辑上划分,一般将磁盘划分为盘符,目录和文件;从抽象物理结构来讲,将磁盘划分为分区,簇和扇区。如何建立逻辑和物理的关系,这就是FAT解决的问题。

       系统在读取一张软盘的时候,会读取软盘上存储的一些关于文件系统的信息,软盘格式化的过程就是系统把文件系统信息写入到软盘上的过程。但是我们不能让系统来格式化我们的boot.img,如果那样,我们写入的启动程序也会被擦除。所以,我们需要自己对软盘进行格式化。 

       一个基本术语:

       扇区(sector):磁盘上的最小数据单元。

       簇(cluster): 一个或多个扇区。

       分区(Partition): 通常指整个文件系统。 

 

       FAT12数据结构:

       FAT文件系统对存储空间分配的最小单位是“簇”,因此文件在占用存储空间时,基本单位是簇而不是字节。即使文件仅仅有1字节大小,系统也必须分给它一个最小存储单元——簇。我们可以设置,是的每簇包含一个扇区。

       FAT的存储空间管理是通过管理FAT表来实现的,FAT表一般位于启动扇区之后,根目录前的若干个扇区,而且一般是两个表。从根目录区的下一个簇开始,每个簇按照它在磁盘上的位置映射到FAT表里。FAT文件系统的存储结构如下: 

                         

       FAT表的表项类似于数据结构中单向链表节点的next指针。在链表中,next指针指向的是下一个相邻节点。那么FAT表与链表的区别:

       1. FAT表将next指针集中管理,放在一起被称为FAT表

       2. FAT表项指向的是固定大小的文件“簇”(data段),而且每个文件簇都有自己对应的FAT表项。由于每个文件簇都有自己的FAT表项,这个表项可能指向另一个文件簇,所以FAT表项所占字节的多少就决定了FAT表最大能管理多少内存,FAT12的FAT表项有12个比特,大约能管理212-个文件簇。 

       一个文件往往要占据多个簇,只要我们知道这个文件的第一个簇,就可以到FAT表里查询该簇对应的FAT表项,该表项的内容一般就是此文件下一个簇号。如果该表项的值大于0xff8,则表示该簇是文件最后一个簇,相当于单向链表节点的next指针为NULL;如果该表项的值是0xff7则表示它是一个坏簇。

      如何找到文件对应的第一个簇,目录结构这时就重要了。以根目录为例介绍:

      根目录存储在磁盘中固定的地方,紧跟在最后一个FAT表之后。根目录的扇区数也是固定的,可以根据BPB_RootEntCnt计算得出:

      RootDirSectors = ((BPB_RootEntCnt*32) + (BPB_BytesPerSec-1))/BPB-BytesPerSec.

      根目录的扇区号是相对于该FAT卷启动扇区的偏移量:

      FirstRootDirSecNum = BPB_RsvdSecCnt + (BPB_NumFATs * BPB_FATz16)

      FAT根目录其实就是一个由32-bytes的线性表构成的文件。其每一个条目代表着一个文件。

      根目录的条目格式:参见杨文博的---《使用开源软件--自己动手写操作系统》 的P29.

      wiki的FAT有详细介绍:http://zh.wikipedia.org/wiki/FAT   

 

 

     于渊的书上有这样一句话:      要把Loader复制到软盘上并让引导扇区找到并加载它。 

     如何让引导扇区找到文件,以及能够把文件内容全都读出来并放进内存里。

     我们让Loader只能放在根目录中,而根目录信息存放在FAT12后面的根目录区中。大小由BPB_RootEntCnt决定,每一个条目占32个字节。