编辑: 施信荣 2019-07-16

???//文件大小 };

3、文件打开表 typedef struct opentable { dir_entry *file;

//打开的文件 unsigned char op_attr;

//打开文件的权限 int blk;

//文件指针所在的块 int off;

//文件指针所在的块内偏移 opentable *next;

}opentable;

六、主要操作的实现: 1.format 格式化 在实验中创建磁盘是创建一个二进制文件.以读/写方式建立一个新的二进制文件,返回一个文件指针(指向文件信息区的起始地址).在以后的程序中,就可通过这个文件指针对文件进行相关的读/写操作. 在格式化操作中,由于文件系统是虚拟在内存中的,所以操作相对较容易.只要将所有FAT表项的内容置为NOT_USED(第0-2块的FAT表项当然要置为END_OF_FILE了), 并在根目录中填好 . 和 .. 项的内容即可. 2.namei ??? 这个操作主要是由一个路径path找到它对应的文件的文件控制块.如path为:a\b\c 那么这个操作就返回:当前目录\a\b\目录下的c文件的文件控制块.主要的实现思路是:找到两个 \ 之间的目录名,如:a, 从当前查找目录里找这个目录,如果没找到则返回错误,如果找到则把a目录设为当前查找目录,继续递归地找,直到找到path的最后一项.在查找中要注意一个目录文件的长度可能大于一个块,这样就要求在FAT表中获得目录文件下一块的块号. 3.create?创建一个文件 ??? 创建一个文件要做两件事情:1.判断该文件是否已经存在.2.创建文件. 假设要创建的文件路径是:a\b\c,那么首先到curr_dir\a\b目录下找c文件(如果连这个目录都没找到那肯定要返回错误了),如果找到说明c文件已经存在,否则为c文件分配空闲的文件控制块并填写相应的属性等信息(如果curr_dir\a\b目录中已经没有空间存放文件控制块了则要申请一个新的块,并修改FAT表项的内容).如果创建的是目录文件则要为它申请新的一块,并在块中填入 . 和 .. 项的内容.由此可见,创建一个普通文件和创建一个目录是不同的,普通文件的初始大小为0,初始块号为END_OF_FILE,而目录文件的初始大小为32,初始块号为getblk()返回的值. 4.rm?删除一个文件 ??? 与create类似. ??? 删除一个文件的时候,为保持目录中有效dir_entry的连续性,将最后一条有效dir_entry的内容拷备到要删除dir_entry中来,并删除最后一条dir_entry. 5.open?打开一个文件 ??? 首先检查下文件是否已经打开.如果没有打开,则由文件对应的path,利namei(path)找到要打开的文件的文件控制块,并加到到open_table(文件打开表)中去. opentable的结构: struct opentable { ?dir_entry *file;

???//打开的文件控制块 ?unsigned char op_attr;

?//打开的文件的属性 ?int? blk;

?????//文件指针所在的块 ?int? off;

?????//文件指针所在的块内偏移 ?opentable *next;

???//指向下一个打开文件表项 } ??? opentable中blk及off表示了当前对此打开的文件的操作己经处于该文件所占磁盘空间的第blk块中的第off个字节的位置.刚打开文件的时候这两个值当然都是0了. 6.close?关闭一个文件 ??? 与open类似. 7.read?从指定的文件中读size个字节到缓冲区中 ??? 首先判断指定的文件是否已经打开.若文件已打开,再由namei(path)找到文件控制 块,开始递归读文件中的数据.在读完文件之后,要修改文件打开表中当前操作(即blk和off)的值.如果要读的字节数size已经起过文件最大长度,则读到文件结尾为止. ??? 最后,返回实际所读的字节数. 8.write?从缓冲区中写size个字节到指定的文件中 ??? 与read操作类似. ??? 在文件刚被创建时,普通文件的size是为0的,因此,若对一个刚被创建的普通文件进行write操作,必须先申请一个空闲块,再进行递归的写操作.而对于刚被创建的目录文件却没有这个问题,因为目录文件被创建的时候size为32(有 . 和 .. 两个目录项了). 9.ls?显示当前目录下的文件和目录 ??? 遍历当前目录下所有的目录项,操作与namei中遍历目录的方法类似. 10.mkdir?创建目录 ??? 利用creae创建目录,属性设为ATTR_DIRECTORY. 11.rmdir?删除目录 ??? 利用rm删除目录. 12.cd?更改当前目录 ??? 利用namei(path)找到要更改到的目录的文件控制块,并将curr_dir置为此值. 13.getblk?得到一个空头块的块号 ??? 从FAT表中找一个内容为NOT_USED的项,返回该项所对应的块号.如果磁盘已满,则返回错误. ??? 每次找的时候从next_blk开始往后查找.next_blk的值将会在releaseblk中做相应的修改. 14.releaseblk??释放块号为blk的块 ??? 将FAT表中blk块对应的表项的内容置为NOT_USED,如果blk的值小于next_blk,则next_blk=blk,保证getblk每次都从块号最小的空闲块开始找. 15.rewind??将打开文件的当前操作位置置为文件头 ??? 首先判断要操作的文件是否打开,若已经打开则将该文件在文件打开表中对应的项的blk设为文件开始块号,off清零.此后对此文件的下一次读或写操作都将从文件头开始. 我们对做好的程序进行检验: 1.?在根目录下写入10个目录,目录名为dir_0~dir_9. 2.?在dir_0中创建一个文件,文件名为file1. 3.?在file1中写入大于BLOCK_SIZE字节的内容,然后重新将它读出. 如果程序正确运行,应该在(第1块,即0x200(512)开始)是FAT表,第0块引导区,第1块FAT表,第2块是根目录,第3块开始为dir_0~dir_9.第13块开始为文件file1. 可以从第1块(0x200)可以看到FAT表. 在根目录(第2块,即0x400开始)下有12个目录项:dir_0~dir_9. 新创建一个目录就会为它分配一个空闲块,那到此为止一共用了13个块:引导块+FAT表+根目录的第一块+10个新分配的目录对应的块.因此,file1文件的开始位置应该是在第13块,即0x1A00,并且FAT表中第13块对应的内容必为0x0E(即指向第14块),因为file1的内容是大于BLOCK_SIZE的! ??? 程序执行完成后的程序所在目录下生成一个disk.dat文件,这就是我们保存到磁盘上的虚拟文件系统.可以打开查看进行验证. ........

下载(注:源文件不在本站服务器,都将跳转到源网站下载)
备用下载
发帖评论
相关话题
发布一个新话题