目录
一、写在前面
在写完了内核线程的代码分析后,我们从本节开始对文件系统的源码分析.本轮代码分析将会涉及nachos文件系统的绝大部分源码文件(除了nachos通用代码部分外如Interrupt等).我们将要分析的文件具体名称如下:BitMap(位于userprog目录下)、Disk(位于machine目录下)、synchdick、filehdr、openfile、directory、filesys.除了两个特别说明的文件,其余文件均位于filesys目录下.
本轮分析采用自底向上的逻辑,旨在理解从低级文件系统到高级文件层层封装的过程,从而对文件系统的业务逻辑有更深刻的认识.虽然名字叫自底向上学习整个文件系统,但我们应当认识到整个nachos系统都是作为Linux的线程存在的,即使是nachos最底层也只是进行编程模拟,这是因为nachos没有驱动程序,不能在裸机上直接运行.文件系统的底层就是依靠调用Linux文件系统API实现的.
在第一节的分析中我们将讲解Disk类与SynchDisk类的源码.
二、源码分析
1、基本磁盘对象:Disk
Disk代表了一个基本磁盘对象,实际上的Disk是使用一个Linux文件进行模拟从而实现数据的持久化存储的.
#define SectorSize 128 // number of bytes per disk sector
#define SectorsPerTrack 32 // number of sectors per disk track
#define NumTracks 32 // number of tracks per disk
#define NumSectors (SectorsPerTrack * NumTracks)
// total # of sectors per disk
class Disk {
public:
Disk(const char* name, VoidFunctionPtr callWhenDone, _int callArg);
// Create a simulated disk.
// Invoke (*callWhenDone)(callArg)
// every time a request completes.
~Disk(); // Deallocate the disk.
void ReadRequest(int sectorNumber, char* data);
// Read/write an single disk sector.
// These routines send a request to
// the disk and return immediately.
// Only one request allowed at a time!
void WriteRequest(int sectorNumber, char* data);
void HandleInterrupt(); // Interrupt handler, invoked when
// disk request finishes.
int ComputeLatency(int newSector, bool writing);
// Return how long a request to
// newSector will take:
// (seek + rotational delay + transfer)
private:
int fileno; // UNIX file number for simulated disk
VoidFunctionPtr handler; // Interrupt handler, to be invoked
// when any disk request finishes
_int handlerArg; // Argument to interrupt handler
bool active; // Is a disk operation in progress?
int lastSector; // The previous disk request
int bufferInit; // When the track buffer started
// being loaded
int TimeToSeek(int newSector, int *rotate); // time to get to the new track
int ModuloDiff(int to, int from); // # sectors between to and from
void UpdateLast(int newSector);
};
在disk.h中,首先定义了四个常量,SectorSize代表了扇区大小、SectorsPerTrack代表了一个磁道上的扇区数目、NumTracks代表了磁道数目、NumSectors代表了总的扇区数目,其值为磁道数目乘以扇区数目.在nachos的文件系统中,磁道这个概念只用于计算寻道时间从而计算磁盘请求时间,真正对模拟磁盘Disk的访问都是以扇区为单位进行的.
Disk类定义了六个数据成员,fileno为调用Linux文件系统获得的打开文件描述符,这个打开文件实际上就是模拟磁盘所在的文件.handler为磁盘请求完成时的回调函数指针,handlerArg为回调函数参数,这两个参数的具体意义我们在后文进行讲解.active用于表示是否正在运行磁盘请求,lastSector记录了最后一次磁盘修改所访问的扇区编号,bufferInit用于某磁盘请求完成后的机器时钟时间.
下面对Disk类的函数进行简介:
- TimeToSeek:计算磁盘的寻道时间
- ModuloDiff:计算两个扇区间相隔的磁道数目