一个简单的文件系统

此文件系统暂时命名为lxfs。使用B+树作为管理结构,但是为了可以容纳更多信息,做了一定的修改。下面是传统的B+树,信息全部保存在叶结点中,通过内部节点进行索引,每一个父级节点的元素索引一个子节点。

一个简单的文件系统_第1张图片

以下是经过修改的B+树,每个父节点可以多索引一个子节点。有利于进一步降低树的高度,容纳更多信息。

一个简单的文件系统_第2张图片

B+树的操作有插入、删除、节点分裂、节点合并、查找、遍历等。

下面是文件索引结构设计:

//B+树内部节点,52kb
#define BNODE_NUM 1401
#define BNODE_SIZE 52*1024
#define CHILD_TYPE_BNODE 0	            //childType属性,内部节点类型
#define CHILD_TYPE_LNODE 3	            //childType属性,叶节点类型
typedef struct BTreeNode {
	extName name[BNODE_NUM];			//文件名描述符数组
	uint32 child[BNODE_NUM + 1];		//子节点指针数组,可能为内部节点或叶节点,使用时,要强制转换为结点指针后使用
	uint16 name_off[BNODE_NUM - 1];		//记录每个文件名的起始下标,从第二个文件名开始
	uint32 parent;			            //父节点指针
	uint16 name_off_num:14;				//记录name_off数组的有效长度
	uint16 childType:2;					//子节点类型,0=内部节点,3=叶节点
	uint16 namenum;						//记录name数组的长度
}BTreeNode, * _btreenode, * _bn;
 
//B+树叶节点
#define LNODE_NUM 2409
//叶节点,80kb
#define LNODE_SIZE 80*1024
typedef struct LeafNode {
	fileItems fi[LNODE_NUM];			//文件描述符数组
	uint16 file_off[LNODE_NUM - 1];		//文件偏移数组,描述文件的起始描述符位下标,由于第一个文件项的下标肯定为0,因此从第二个文件描述符开始。
	uint16 finum;						//fi数组有效项的长度
	uint16 file_off_num;				//file_off数组有效项的数量
	uint32 prev;				        //前驱节点
	uint32 next;				        //后继节点
	uint32 parent;			            //父节点指针
}LeafNode, * _leafnode, * _ln;

分为两种,一个是叶节点用来保存有关文件的信息,一个是内部节点,用来索引叶节点。由于文件信息需要的储存空间不同,因此在节点结构中设计了偏移数组,用于记录每一个信息元素的位置。由于增加了这些设计,使B+树在实现上也变得更加复杂。

lxfs保存文件信息的结构称为文件描述符。文件描述符的设计参考了FAT32,但是做了一定修改。如下

//文件属性/f分区属性
typedef struct {
    byte dpl : 2;            //文件权限;分区权限 0,1,2,3
    byte extname : 1;        //下一项描述符类型,=0,文件描述符;=1,扩展文件名描述符
    byte isext : 1;            //本描述符是否为扩展描述符,=1
    byte data : 1;            //=1文件正常,=0此文件可能存在问题;作为分区描述符时,=1说明此分区是系统分区,
    byte en_folder : 1;        //说明floder项有效,以此文件名作为后面文件的目录基准,同目录下的文件应该只有一个文件的此项为1
    byte hide : 1;            //=1隐藏文件;=1隐藏分区
    byte del : 1;            //=1已删除文件,相当于放入回收站,标记删除,为了保证可以恢复;=1分区删除
}fileAtt;
 
//文件日期结构
typedef struct {
    uint32 s : 6;        //秒
    uint32 m : 6;        //分
    uint32 h : 5;        //时
    uint32 day : 5;        //日
    uint32 month : 4;    //月
    uint32 year : 6;    //年,使用是将此值加上基准年份等于时间
}fDate, * _fdate;
 
//用于描述符文件信息的文件描述符
typedef struct {
    byte ms : 7;            //创建时间的10毫秒位,ms*10=大约的创建时间,现在感觉这项没什么用
    byte dis : 1;            //=0扩展文件名描述符,=1文件描述符,此项恒等于1
    fileAtt fatt;            //文件属性
    char name[FTNAME_SIZE];            //文件名,占用6字节
    fDate createDate;        //创建日期
    fDate lastVisitDate;    //最后访问日期
    fDate lastModifiedDate;    //最后修改日期
    uint32 size;                //文件长度,单位4kb,因此一个文件最大为4096GB=4TB
    uint32 position;            //在分区内的偏移位置,单位4kb,最大检索16tb,因此一个分区的最大为16tb
    uint16 offset : 12;        //文件占用的最后一个4kb内的偏移
    uint16 extnum : 4;            //扩展描述符数量,最大为15个,当此值=15时,应当查看最后一个扩展描述符,确定是否还有扩展描述符
    uint16 folder;                //文件夹包含数量,如果fatt.en_folder=1,说明此文件描述符组为文件夹描述符,则folder包含了该文件夹的文件数量
}fileTable, * _filetable;
 
//用于储存文件名的文件名描述符
typedef struct extName {
	byte size : 5;			//本项文本串长度
	byte ext : 1;			//1=有扩展项,此项为了避免文件描述符指出的15项的限制,以期能够储存更多文件项
	byte start : 1;			//=1起始项,为扩展文件名描述符组的首项
	byte dis : 1;			//=0扩展文件名描述符,=1文件描述符,此项应该恒等于0
	char name[31];			//文件名
}extName, * _extname;
 
//文件项联合体,一个文件项可能是文件描述符,也可能是扩展文件名描述项
typedef union {
	fileTable ft;			//文件描述符
	extName en;			//扩展文件名描述符
}fileItems, * _fileitems;

fileTable用于储存文件信息,32字节;

extName用于储存扩展文件名信息,32字节。

但是一个fileTable可能无法保存文件的所有信息,因此在现有设计中,设计了文件描述符组来储存信息。一个文件描述符组中描述符的数量是不定的,但是最高允许拥有16个fileTable和15个extName。第一个fileTable称为主文件描述符,记录当前组的描述符,记录其后属于同一组的描述符的数量。

另见:https://blog.csdn.net/lindorx/article/details/104015995

github:https://github.com/lindorx/LX-File-System

测试结果:

一个简单的文件系统_第3张图片


一个简单的文件系统_第4张图片

你可能感兴趣的:(c++,计算机)