首页 理论教育 操作系统实现之路管理器

操作系统实现之路管理器

时间:2023-10-21 理论教育 版权反馈
【摘要】:每当文件系统检测到一个属于自己管理的卷,则文件系统驱动程序会创建一个对应的卷设备对象,并调用AddFileSystem添加到系统中。最后一个变量VolumeLbl则是卷标,定义为13B的长度,包含结尾的0字符。在IOManager初始化的时候,FsArray数组被初始化为全0。图12-4进一步示意了卷设备对象数组FsArray和文件系统设备对象数组FsCtrlArray之间的关系:图12-4 卷设备对象和文件系统设备对象的关系针对系统中的每个文件卷,都会创建一个文件卷对象,并加入FsArray数组。

操作系统实现之路管理器

虽然IOManager对象的定义比较复杂,而且第10章已经介绍了IOManager对象的定义,但是我们还是把这个对象的定义再次呈现在这里,以方便阅读和说明:

978-7-111-41444-5-Chapter12-11.jpg

978-7-111-41444-5-Chapter12-12.jpg

978-7-111-41444-5-Chapter12-13.jpg

这个全局对象提供了应用程序的服务接口,应用程序可以调用诸如CreateFile/ReadFile等函数,完成文件和设备的访问。同时还提供了面向设备驱动程序的服务接口,设备驱动程序可以调用CreateDevice等函数,完成设备对象的创建。这些内容在第10章中已做了详细介绍。接下来重点看IOManager对象提供的面向文件系统的变量和服务接口。

首先看FsArray数组,这是个类型为__FS_ARRAY_ELEMENT、长度为16的数组,这个数组用于记录系统中的所有文件卷。下面是__FS_ARRAY_ELEMENT的定义:

978-7-111-41444-5-Chapter12-14.jpg

这个对象的第一个变量FileSystemIdentifier就是文件卷标识符,比如C:、D:等。在打开一个文件的时候,系统会在给出的文件全名(比如C:\WINDOWS\DATA.TXT)中提取出卷标识符,然后逐个匹配这个数组。一旦卷标识符能够匹配,就可找到对应的pFileSystemObject指针,这个指针指向了具体的卷设备对象。卷设备对象是由文件系统驱动程序针对卷来创建的。每当文件系统检测到一个属于自己管理的卷,则文件系统驱动程序会创建一个对应的卷设备对象,并调用AddFileSystem添加到系统中。卷设备对象对应的驱动程序,即是文件系统驱动程序。

找到卷设备对象之后,即可调用设备对象所对应驱动程序的DeviceOpen函数,来打开文件。DeviceOpen是设备驱动程序对象提供的标准函数之一,用于打开一个设备。在文件系统中,这个函数用于打开一个指定的文件。

dwAttribute则是文件卷的一些属性,比如是否可移动、是否为系统卷等。最后一个变量VolumeLbl则是卷标,定义为13B的长度,包含结尾的0字符

在IOManager初始化的时候,FsArray数组被初始化为全0。在文件系统初始化的时候,会根据对存储设备或分区的检测情况,调用AddFileSystem函数,在这个数组中增加对应的文件卷。显然,AddFileSystem函数的参数是与__FS_ARRAY_ELEMENT结构体中的成员变量一一对应的。这个函数的实现也很简单,无非是从头开始依次检查每个数组元素,试图找到一个未用(FileSystemIdentifier为0)的元素。如果能够找到一个,则把对应的数据添加到里面,否则返回FALSE。下面是其实现代码,为了简便,我们省略了相关注释和无关紧要的代码:

978-7-111-41444-5-Chapter12-15.jpg(www.xing528.com)

978-7-111-41444-5-Chapter12-16.jpg

代码比较简单,但是考虑到这段代码很可能是在设备驱动程序加载和初始化的时候被调用的,而FsArray是一个全局变量,因此使用关键区段对其进行保护,以免发生数据不一致的情况。另外,对于卷标的复制,也是采用了最简单的逐个字符复制的方式,这是为了最大可能地提高代码的安全性,毕竟strcpy等函数存在一定的风险。虽然这样做效率比较低,但是考虑到这个函数被调用的次数不会太多,而且卷标也不是太长,这个牺牲效率换安全的做法还是值得的。在Hello China的内核代码中,很多情况都是采用了这种策略,比如创建核心线程的时候,线程名字的复制也是采用了这种安全的方法。

下面再看FSCtrlArray,这个数组就是文件系统设备对象数组。针对Hello China支持的每种文件管理系统,比如NTFS、FAT32、CDFS等,在这个数组中都会有一个文件系统设备对象与之对应。IOManager初始化的时候,这个数组被清零。在文件系统驱动程序加载过程中,每个文件管理系统都会创建一个文件系统设备对象,并调用RegisterFileSystem添加到系统中。下面是RegisterFileSystem的实现代码(做了删减):

978-7-111-41444-5-Chapter12-17.jpg

978-7-111-41444-5-Chapter12-18.jpg

比较简单,就是在FsCtrlArray中寻找一个空闲的元素,然后把参数给出的文件系统设备对象复制到这个元素中。如果所有数组元素都不为NULL,则失败返回。FsCtrlArray的长度预定义为4,即最大可以支持4个文件系统,这对目前的应用来说已经足够了。

图12-4进一步示意了卷设备对象数组FsArray和文件系统设备对象数组FsCtrlArray之间的关系:

978-7-111-41444-5-Chapter12-19.jpg

图12-4 卷设备对象和文件系统设备对象的关系

针对系统中的每个文件卷,都会创建一个文件卷对象,并加入FsArray数组。针对系统中的每个文件管理系统,都会有一个文件系统设备对象与之对应。类型相同的文件卷和文件管理系统,都指向一个相同的文件系统驱动程序对象。

AddFileSystem和RegisterFileSystem两个函数,以及对应的FsArray和FsCtrlArray两个数组,是文件系统功能可扩展、可支持存储设备的动态插拔的基础。下面我们以FAT32文件系统驱动程序为例,具体看一下文件系统的初始化过程。在初始化过程中会调用上述两个函数。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈