资源描述
- .
操作系统课程设计报告
小组编号: 小组成员:
一、课程设计概述:
1、题目:简单文件系统的实现
2、实现容
(1) 在存中开辟一个虚拟磁盘空间作为文件存储分区,在其上实现一个简单的基于多级目录的单用户单任务系统中的文件系统。在退出该文件系统的使用时,应将该虚拟文件系统以一个Windows 文件的方式保存到磁盘上,以便下次可以再将它恢复到存的虚拟磁盘空间中。
(2) 文件存储空间的分配可采用显式分配或其他的方法。
(3) 空闲磁盘空间的管理可选择位示图或其他的方法。如果采用位示图来管理文件存储空间,并采用显式分配方式,那么可以将位示图合并到FAT中。
(4) 文件目录构造采用多级目录构造。为了简单起见,可以不使用索引结点,其中的每个目录项应包含文件名、物理地址、长度等信息,还可以通过目录项实现对文件的读和写的保护。
(5) 要求提供以下操作命令:
l my_format:对文件存储器进展格式化,即按照文件系统的构造对虚拟磁盘空间进展布局,并在其上创立根目录以及用于管理文件存储空间等的数据构造。
l my_mkdir:用于创立子目录。
l my_rmdir:用于删除子目录。
l my_ls:用于显示目录中的容。
l my_cd:用于更改当前目录。
l my_create:用于创立文件。
l my_open:用于翻开文件。
l my_close:用于关闭文件。
l my_write:用于写文件。
l my_read:用于读文件。
l my_rm:用于删除文件。
l my_exitsys:用于退出文件系统。
二、 设计思路〔主要算法描述、程序流程图等〕:
1.系统主函数main()
〔1〕对应命令:无
〔2〕命令调用格式:无
〔3〕函数设计格式:void main()
〔4〕功能:系统主函数
〔5〕输入:无
〔6〕输出:无
〔7〕函数需完成的工作:
① 对前面定义的全局变量进展初始化;
② 调用startsys()进入文件系统;
③ 列出文件系统提供的各项功能及命令调用格式;
④ 显示命令行提示符,等待用户输入命令;
⑤ 将用户输入的命令保存到一个buf中;
⑥ 对buf中的容进展命令解析,并调用相应的函数执行用户键入的命令;
⑦ 如果命令不是“my_exitsys〞,那么命令执行完毕后转④。
2. 进入文件系统函数startsys()
〔1〕对应命令:无
〔2〕命令调用格式:无
〔3〕函数设计格式:void startsys()
〔4〕功能:由main()函数调用,进入并初始化我们所建立的文件系统,以供用户使用。
〔5〕输入:无
〔6〕输出:无。
〔7〕函数需完成的工作:
① 申请虚拟磁盘空间;
② 使用c语言的库函数fopen()翻开myfsys文件:假设文件存在,那么转③;假设文件不存在,那么创立之,转⑤
③ 使用c语言的库函数fread()读入myfsys文件容到用户空间中的一个缓冲区中,并判断其开场的8个字节容是否为“10101010〞〔文件系统魔数〕,如果是,那么转④;否那么转⑤;
④ 将上述缓冲区中的容复制到存中的虚拟磁盘空间中;转⑦
⑤ 在屏幕上显示“myfsys文件系统不存在,现在开场创立文件系统〞信息,并调用my_format()对①中申请到的虚拟磁盘空间进展格式化操作。转⑥;
⑥ 将虚拟磁盘中的容保存到myfsys文件中;转⑦
⑦ 使用c语言的库函数fclose()关闭myfsys文件;
⑧ 初始化用户翻开文件表,将表项0分配给根目录文件使用,并填写根目录文件的相关信息,由于根目录没有上级目录,所以表项中的dirno和diroff分别置为5〔根目录所在起始块号〕和0;并将ptrcurdir指针指向该用户翻开文件表项。
⑨ 将当前目录设置为根目录。
3.磁盘格式化函数my_format()
〔1〕对应命令:my_format
〔2〕命令调用格式:my_format
〔3〕函数设计格式:void my_format()
〔4〕功能:对虚拟磁盘进展格式化,布局虚拟磁盘,建立根目录文件〔或根目录区〕。
〔5〕输入:无
〔6〕输出:无。
〔7〕函数需完成的工作:
① 将虚拟磁盘第一个块作为引导块,开场的8个字节是文件系统的魔数,记为“10101010〞;在之后写入文件系统的描述信息,如FAT表大小及位置、根目录大小及位置、盘块大小、盘块数量、数据区开场位置等信息;
② 在引导块后建立两完全一样的FAT表,用于记录文件所占据的磁盘块及管理虚拟磁盘块的分配,每个FAT占据两个磁盘块;对于每个FAT中,前面5个块设置为已分配,后面995个块设置为空闲;
③ 在第二FAT后创立根目录文件root,将数据区的第1块〔即虚拟磁盘的第6块〕分配给根目录文件,在该磁盘上创立两个特殊的目录项:“.〞和“..〞,其容除了文件名不同之外,其他字段完全一样。
4.更改当前目录函数my_cd()
〔1〕对应命令:my_cd
〔2〕命令调用格式:my_cd dirname
〔3〕函数设计格式:void my_cd(char *dirname)
〔4〕功能:改变当前目录到指定的名为dirname的目录。
〔5〕输入:
dirname:新的当前目录的目录名;
〔6〕输出:无
〔7〕函数需完成的工作:
① 调用my_open()翻开指定目录名的父目录文件,并调用do_read()读入该父目录文件容到存中;
② 在父目录文件中检查新的当前目录名是否存在,如果存在那么转③,否那么返回,并显示出错信息;
③ 调用my_close()关闭①中翻开的父目录文件;
④ 调用my_close()关闭原当前目录文件;
⑤ 如果新的当前目录文件没有翻开,那么翻开该目录文件;并将ptrcurdir指向该翻开文件表项;
⑥ 设置当前目录为该目录。
5.创立子目录函数my_mkdir()
〔1〕对应命令:my_mkdir
〔2〕命令调用格式:my_ mkdir dirname
〔3〕函数设计格式:void my_mkdir(char *dirname)
〔4〕功能:在当前目录下创立名为dirname的子目录。
〔5〕输入:
dirname:新建目录的目录名。
〔6〕输出:无。
〔7〕函数需完成的工作:
① 调用do_read()读入当前目录文件容到存,检查当前目录下新建目录文件是否重名,假设重名那么返回,并显示错误信息;
② 为新建子目录文件分配一个空闲翻开文件表项,如果没有空闲表项那么返回-1,并显示错误信息;
③ 检查FAT是否有空闲的盘块,如有那么为新建目录文件分配一个盘块,否那么释放①中分配的翻开文件表项,返回,并显示错误信息;
④ 在当前目录中为新建目录文件寻找一个空闲的目录项或为其追加一个新的目录项;需修改当前目录文件的长度信息,并将当前目录文件的用户翻开文件表项中的fcbstate置为1;
⑤ 准备好新建目录文件的FCB的容,文件的属性为目录文件,以覆盖写方式调用do_write()将其填写到对应的空目录项中;
⑥ 在新建目录文件所分配到的磁盘块中建立两个特殊的目录项“.〞和“..〞目录项,方法是:首先在用户空间中准备好容,然后以截断写或者覆盖写方式调用do_write()将其写到③中分配到的磁盘块中;
⑦ 返回。
6.删除子目录函数rmdir()
〔1〕对应命令:my_ rmdir
〔2〕命令调用格式:my_ rmdir dirname
〔1〕函数设计格式:void my_rmdir(char *dirname)
〔2〕功能:在当前目录下删除名为dirname的子目录。
〔3〕输入:
dirname:欲删除目录的目录名。
〔4〕输出:无。
〔5〕函数需完成的工作:
① 调用do_read()读入当前目录文件容到存,检查当前目录下欲删除目录文件是否存在,假设不存在那么返回,并显示错误信息;
② 检查欲删除目录文件是否为空〔除了“.〞和“..〞外没有其他子目录和文件〕,可根据其目录项中记录的文件长度来判断,假设不为空那么返回,并显示错误信息;
③ 检查该目录文件是否已经翻开,假设已翻开那么调用my_close()关闭掉;
④ 回收该目录文件所占据的磁盘块,修改FAT;
⑤ 从当前目录文件中清空该目录文件的目录项,且free字段置为0:以覆盖写方式调用do_write()来实现;
⑥ 修改当前目录文件的用户翻开表项中的长度信息,并将表项中的fcbstate置为1;
⑦ 返回。
7.显示目录函数my_ls()
〔1〕对应命令:my_ls
〔2〕命令调用格式:my_ls
〔3〕函数设计格式:void my_ls(void)
〔4〕功能:显示当前目录的容〔子目录和文件信息〕。
〔5〕输入:无
〔6〕输出:无
〔7〕函数需完成的工作:
① 调用do_read()读出当前目录文件容到存;
② 将读出的目录文件的信息按照一定的格式显示到屏幕上;
③ 返回。
8.创立文件函数my_create()
〔1〕对应命令:my_create
〔2〕命令调用格式:my_create filename
〔3〕函数设计格式:int my_create (char *filename)
〔4〕功能:创立名为filename的新文件。
〔5〕输入:
filename:新建文件的文件名,可能包含路径。
〔6〕输出:假设创立成功,返回该文件的文件描述符〔文件翻开表中的数组下标〕;否那么返回-1。
〔7〕函数需完成的工作:
① 为新文件分配一个空闲翻开文件表项,如果没有空闲表项那么返回-1,并显示错误信息;
② 假设新文件的父目录文件还没有翻开,那么调用my_open()翻开;假设翻开失败,那么释放①中为新建文件分配的空闲文件翻开表项,返回-1,并显示错误信息;
③ 调用do_read()读出该父目录文件容到存,检查该目录下新文件是否重名,假设重名那么释放①中分配的翻开文件表项,并调用my_close()关闭②中翻开的目录文件;然后返回-1,并显示错误信息;
④ 检查FAT是否有空闲的盘块,如有那么为新文件分配一个盘块,否那么释放①中分配的翻开文件表项,并调用my_close()关闭②中翻开的目录文件;返回-1,并显示错误信息;
⑤ 在父目录中为新文件寻找一个空闲的目录项或为其追加一个新的目录项;需修改该目录文件的长度信息,并将该目录文件的用户翻开文件表项中的fcbstate置为1;
⑥ 准备好新文件的FCB的容,文件的属性为数据文件,长度为0,以覆盖写方式调用do_write()将其填写到⑤中分配到的空目录项中;
⑦ 为新文件填写①中分配到的空闲翻开文件表项,fcbstate字段值为0,读写指针值为0;
⑧ 调用my_close()关闭②中翻开的父目录文件;
⑨ 将新文件的翻开文件表项序号作为其文件描述符返回。
9.删除文件函数my_rm()
〔1〕对应命令:my_rm
〔2〕命令调用格式:my_rm filename
〔3〕函数设计格式:void my_rm(char *filename)
〔4〕功能:删除名为filename的文件。
〔5〕输入:
filename:欲删除文件的文件名,可能还包含路径。
〔6〕输出:无。
〔7〕函数需完成的工作:
① 假设欲删除文件的父目录文件还没有翻开,那么调用my_open()翻开;假设翻开失败,那么返回,并显示错误信息;
② 调用do_read()读出该父目录文件容到存,检查该目录下欲删除文件是否存在,假设不存在那么返回,并显示错误信息;
③ 检查该文件是否已经翻开,假设已翻开那么关闭掉;
④ 回收该文件所占据的磁盘块,修改FAT;
⑤ 从文件的父目录文件中清空该文件的目录项,且free字段置为0:以覆盖写方式调用do_write()来实现;;
⑥ 修改该父目录文件的用户翻开文件表项中的长度信息,并将该表项中的fcbstate置为1;
⑦ 返回。
10.翻开文件函数my_open()
〔1〕对应命令:my_open
〔2〕命令调用格式:my_open filename
〔3〕函数设计格式:int my_open(char *filename)
〔4〕功能:翻开当前目录下名为filename的文件。
〔5〕输入:
filename:欲翻开文件的文件名
〔6〕输出:假设翻开成功,返回该文件的描述符〔在用户翻开文件表中表项序号〕;否那么返回-1。
〔7〕函数需完成的工作:
① 检查该文件是否已经翻开,假设已翻开那么返回-1,并显示错误信息;
② 调用do_read()读出父目录文件的容到存,检查该目录下欲翻开文件是否存在,假设不存在那么返回-1,并显示错误信息;
③ 检查用户翻开文件表中是否有空表项,假设有那么为欲翻开文件分配一个空表项,假设没有那么返回-1,并显示错误信息;
④ 为该文件填写空白用户翻开文件表表项容,读写指针置为0;
⑤ 将该文件所分配到的空白用户翻开文件表表项序号〔数组下标〕作为文件描述符fd返回。
11.关闭文件函数my_close()
〔1〕对应命令:my_close
〔2〕命令调用格式:my_close fd
〔3〕函数设计格式:void my_close(int fd)
〔4〕功能:关闭前面由my_open()翻开的文件描述符为fd的文件。
〔5〕输入:
fd:文件描述符。
〔6〕输出:无。
〔7〕函数需完成的工作:
① 检查fd的有效性〔fd不能超出用户翻开文件表所在数组的最大下标〕,如果无效那么返回-1;
② 检查用户翻开文件表表项中的fcbstate字段的值,如果为1那么需要将该文件的FCB的容保存到虚拟磁盘上该文件的目录项中,方法是:翻开该文件的父目录文件,以覆盖写方式调用do_write()将欲关闭文件的FCB写入父目录文件的相应盘块中;
③ 回收该文件占据的用户翻开文件表表项〔进展清空操作〕,并将topenfile字段置为0;
④ 返回。
12.写文件函数my_write()
〔1〕对应命令:my_write
〔2〕命令调用格式:my_write fd
〔3〕函数设计格式:int my_write(int fd)
〔4〕功能:将用户通过键盘输入的容写到fd所指定的文件中。磁盘文件的读写操作都必须以完整的数据块为单位进展,在写操作时,先将数据写在缓冲区中,缓冲区的大小与磁盘块的大小一样,然后再将缓冲区中的数据一次性写到磁盘块中;读出时先将一个磁盘块中的容读到缓冲区中,然后再传送到用户区。本实例为了简便起见,没有设置缓冲区管理,只是在读写文件时由用户使用malloc()申请一块空间作为缓冲区,读写操作完毕后使用free()释放掉。
写操作常有三种方式:截断写、覆盖写和追加写。截断写是放弃原来文件的容,重新写文件;覆盖写是修改文件在当前读写指针所指的位置开场的局部容;追加写是在原文件的最后添加新的容。在本实例中,输入写文件命令后,系统会出现提示让用户选择其中的一种写方式,并将随后键盘输入的容按照所选的方式写到文件中,键盘输入容通过CTR+Z键〔或其他设定的键〕完毕。
〔5〕输入:
fd: open()函数的返回值,文件的描述符;
〔6〕输出:实际写入的字节数。
〔7〕函数需完成的工作:
① 检查fd的有效性〔fd不能超出用户翻开文件表所在数组的最大下标〕,如果无效那么返回-1,并显示出错信息;
② 提示并等待用户输入写方式:〔1:截断写;2:覆盖写;3:追加写〕
③ 如果用户要求的写方式是截断写,那么释放文件除第一块外的其他磁盘空间容〔查找并修改FAT表〕,将存用户翻开文件表项中文件长度修改为0,将读写指针置为0并转④;如果用户要求的写方式是追加写,那么修改文件的当前读写指针位置到文件的末尾,并转④;如果写方式是覆盖写,那么直接转④;
④ 提示用户:整个输入容通过CTR+Z键〔或其他设定的键〕完毕;用户可分屡次输入写入容,每次用回车完毕;
⑤ 等待用户从键盘输入文件容,并将用户的本次输入容保存到一临时变量text[]中,要求每次输入以回车完毕,全部完毕用CTR+Z键〔或其他设定的键〕;
⑥ 调用do_write()函数将通过键盘键入的容写到文件中。
⑦ 如果do_write()函数的返回值为非负值,那么将实际写入字节数增加do_write()函数返回值,否那么显示出错信息,并转⑨;
⑧ 如果text[]中最后一个字符不是完毕字符CTR+Z,那么转⑦继续进展写操作;否那么转⑨;
⑨ 如果当前读写指针位置大于用户翻开文件表项中的文件长度,那么修改翻开文件表项中的文件长度信息,并将fcbstate置1;
⑩ 返回实际写入的字节数。
13.实际写文件函数do_write()
〔1〕对应命令:无
〔2〕命令调用格式:无
〔3〕函数设计格式:int my_write(int fd,char *text,int len,char wstyle)
〔4〕功能:被写文件函数my_write()调用,用来将键盘输入的容写到相应的文件中去。
〔5〕输入:
fd: open()函数的返回值,文件的描述符;
text:指向要写入的容的指针;
len:本次要求写入字节数
wstyle:写方式
〔6〕输出:实际写入的字节数。
〔7〕函数需完成的工作:
① 用malloc()申请1024B的存空间作为读写磁盘的缓冲区buf,申请失败那么返回-1,并显示出错信息;
② 将读写指针转化为逻辑块块号和块偏移off,并利用翻开文件表表项中的首块号及FAT表的相关容将逻辑块块号转换成对应的磁盘块块号blkno;如果找不到对应的磁盘块,那么需要检索FAT为该逻辑块分配一新的磁盘块,并将对应的磁盘块块号blkno登记到FAT中,假设分配失败,那么返回-1,并显示出错信息;
③ 如果是覆盖写,或者如果当前读写指针所对应的块偏移off不等于0,那么将块号为blkno的虚拟磁盘块全部1024B的容读到缓冲区buf中;否那么便用ASCII码0清空buf;
④ 将text中未写入的容暂存到缓冲区buff的第off字节开场的位置,直到缓冲区满,或者接收到完毕字符CTR+Z为止;将本次写入字节数记录到tmplen中;
⑤ 将buf中1024B的容写入到块号为blkno的虚拟磁盘块中;
⑥将当前读写指针修改为原来的值加上tmplen;并将本次实际写入的字节数增加tmplen;
⑦ 如果tmplen小于len,那么转②继续写入;否那么转⑧;
⑧ 返回本次实际写入的字节数。
14.读文件函数my_read()
〔1〕对应命令:my_read
〔2〕命令调用格式:my_read fd len
〔3〕函数设计格式:int myread (int fd, int len)
〔4〕功能:读出指定文件中从读写指针开场的长度为len的容到用户空间中。
〔5〕输入:
fd: open()函数的返回值,文件的描述符;
len: 要从文件中读出的字节数。
〔6〕输出:实际读出的字节数。
〔7〕函数需完成的工作:
① 定义一个字符型数组text[len],用来接收用户从文件中读出的文件容;
② 检查fd的有效性〔fd不能超出用户翻开文件表所在数组的最大下标〕,如果无效那么返回-1,并显示出错信息;
③ 调用do_read()将指定文件中的len字节容读出到text[]中;
④ 如果do_read()的返回值为负,那么显示出错信息;否那么将text[]中的容显示到屏幕上;
⑤ 返回。
15.实际读文件函数do_read()
〔1〕对应命令:无
〔2〕命令调用格式:无
〔3〕函数设计格式:int do_read (int fd, int len,char *text)
〔4〕功能:被my_read()调用,读出指定文件中从读写指针开场的长度为len的容到用户空间的text中。
〔5〕输入:
fd: open()函数的返回值,文件的描述符;
len: 要求从文件中读出的字节数。
text:指向存放读出数据的用户区地址
〔6〕输出:实际读出的字节数。
〔7〕函数需完成的工作:
① 使用malloc()申请1024B空间作为缓冲区buf,申请失败那么返回-1,并显示出错信息;
② 将读写指针转化为逻辑块块号及块偏移量off,利用翻开文件表表项中的首块号查找FAT表,找到该逻辑块所在的磁盘块块号;将该磁盘块块号转化为虚拟磁盘上的存位置;
③ 将该存位置开场的1024B〔一个磁盘块〕容读入buf中;
④ 比拟buf中从偏移量off开场的剩余字节数是否大于等于应读写的字节数len,如果是,那么将从off开场的buf中的len长度的容读入到text[]中;否那么,将从off开场的buf中的剩余容读入到text[]中;
⑤ 将读写指针增加④中已读字节数,将应读写的字节数len减去④中已读字节数,假设len大于0,那么转②;否那么转⑥;
⑥ 使用free()释放①中申请的buf。
⑦ 返回实际读出的字节数。
16. 退出文件系统函数my_exitsys()
〔1〕对应命令:my_exitsys
〔2〕命令调用格式:my_ exitsys
〔1〕函数设计格式:void my_exitsys()
〔2〕功能:退出文件系统。
〔3〕输入:无
〔4〕输出:无。
〔5〕函数需完成的工作:
① 使用C库函数fopen()翻开磁盘上的myfsys文件;
② 将虚拟磁盘空间中的所有容保存到磁盘上的myfsys文件中;
③ 使用c语言的库函数fclose()关闭myfsys文件;
④ 撤销用户翻开文件表,释放其存空间
⑤ 释放虚拟磁盘空间。
程序启动
流程图
文件系统是否存在
加载文件系统
是
否
创立文件系统,并格式化
等待用户命令输入
用户输入命令
my_exitsys
my_open
my_rm
my_create
my_ls
……
三、 程序实现代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define BLOCKSIZE 1024 // 磁盘块大小
#define SIZE 1024000 // 虚拟磁盘空间大小
#define END 65535 // FAT中的文件完毕标志
#define FREE 0 // FAT中盘块空闲标志
#define ROOTBLOCKNUM 2 // 根目录区所占盘块数
#define MAXOPENFILE 10 // 最多同时翻开文件个数t
#define MAXTEXT 10000
/* 文件控制块 */
typedef struct FCB{
char filename[8]; // 文件名
char exname[3]; // 文件扩展名
unsigned char attribute; // 文件属性字段,值为0时表示目录文件,值为1时表示数据文件
unsigned short time; // 文件创立时间
unsigned short date; // 文件创立日期
unsigned short first; // 文件起始盘块号
unsigned long length; // 文件长度
char free; // 表示目录项是否为空,假设值为0,表示空,值为1,表示已分配
}fcb;
/* 文件分配表 */
typedef struct FAT
{
unsigned short id; // 磁盘块的状态〔空闲的,最后的,下一个〕
}fat;
/* 用户翻开文件表 */
typedef struct USEROPEN
{
char filename[8]; // 文件名
char exname[3]; // 文件扩展名
unsigned char attribute;//文件属性字段,值为0时表示目录文件,值为1时表示数据文件
unsigned short time; // 文件创立时间
unsigned short date; // 文件创立日期
unsigned short first; // 文件起始盘块号
unsigned long length;//文件长度〔对数据文件是字节数,对目录文件可以是目录项个数〕
char free; // 表示目录项是否为空,假设值为0,表示空,值为1,表示已分配
unsigned short dirno; // 相应翻开文件的目录项在父目录文件中的盘块号
int diroff; // 相应翻开文件的目录项在父目录文件的dirno盘块中的目录项序号
char dir[80]; // 相应翻开文件所在的路径名,这样方便快速检查出指定文件是否已经翻开
int father; // 父目录在翻开文件表项的位置
int count; // 读写指针在文件中的位置,文件的总字符数
char fcbstate; // 是否修改了文件的FCB的容,如果修改了置为1,否那么为0
char topenfile; // 表示该用户翻开表项是否为空,假设值为0,表示为空,否那么表示已被某翻开文件占据
}useropen;
/* 引导块 */
typedef struct BLOCK0
{
char magic[10]; // 文件系统魔数
char information[200];//存储一些描述信息,如磁盘块大小、磁盘块数量、最多翻开文件数等
unsigned short root; // 根目录文件的起始盘块号
unsigned char *startblock; // 虚拟磁盘上数据区开场位置
}block0;
unsigned char *myvhard; // 指向虚拟磁盘的起始地址
useropen openfilelist[MAXOPENFILE]; // 用户翻开文件表数组
int curdir; // 用户翻开文件表中的当前目录所在翻开文件表项的位置
char currentdir[80]; // 记录当前目录的目录名〔包括目录的路径〕
unsigned char* startp; // 记录虚拟磁盘上数据区开场位置
char myfilename[] = "myfilesys";//文件系统的文件名
void startsys(); // 进入文件系统
void my_format(); // 磁盘格式化
void my_cd(char *dirname); // 更改当前目录
void my_mkdir(char *dirname); // 创立子目录
void my_rmdir(char *dirname); // 删除子目录
void my_ls(); // 显示目录
void my_create (char *filename); // 创立文件
void my_rm(char *filename); // 删除文件
int my_open(char *filename); // 翻开文件
int my_close(int fd); // 关闭文件
int my_write(int fd); // 写文件
int do_write(int fd, char *text, int len, char wstyle); // 实际写文件
int my_read (int fd, int len); // 读文件
int do_read (int fd, int len,char *text); // 实际读文件
void my_exitsys(); // 退出文件系统
unsigned short findblock(); // 寻找空闲盘块
int findopenfile(); // 寻找空闲文件表项
void startsys()
{
FILE *fp;
unsigned char buf[SIZE];
fcb *root;
int i;
myvhard = (unsigned char *)malloc(SIZE);//申请虚拟磁盘空间
memset(myvhard, 0, SIZE);//将myvhard中前SIZE个字节用 0 替换并返回 myvhard
if((fp = fopen(myfilename, "r")) != NULL)
{
fread(buf, SIZE, 1, fp);//将二进制文件读取到缓冲区
fclose(fp);
if(strcmp(((block0 *)buf)->magic, "10101010"))
{
printf("myfilesys is not exist,begin to creat the file...\n");
my_format();
}
else
{
for(i = 0; i < SIZE; i++)
myvhard[i] = buf[i];
}
}
else
{
printf("myfilesys is not exist,begin to creat the file...\n");
my_format();
}
root = (fcb *)(myvhard + 5 * BLOCKSIZE);
strcpy(openfilelist[0].filename, root->filename);
strcpy(openfilelist[0].exname, root->exname);
openfilelist[0].attribute = root->attribute;
openfilelist[0].time = root->time;
openfilelist[0].date = root->date;
openfilelist[0].first = root->first;
openfilelist[0].length = root->length;
openfilelist[0].free = root->free;
openfilelist[0].dirno = 5;
openfilelist[0].diroff = 0;
strcpy(openfilelist[0].dir, "\\root\\");
openfilelist[0].father = 0;
openfilelist[0].count = 0;
openfilelist[0].fcbstate = 0;
openfilelist[0].topenfile = 1;
for(i = 1; i < MAXOPENFILE; i++)
openfilelist[i].topenfile = 0;
curdir = 0;
strcpy(currentdir, "\\root\\");
startp = ((block0 *)myvhard)->startblock;
}
void my_format()
{
FILE *fp;
fat *fat1, *fat2;
block0 *blk0;
time_t now;
struct tm *nowtime;
fcb *root;
int i;
blk0 = (block0 *)myvhard;
fat1 = (fat *)(myvhard + BLOCKSIZE);
fat2 = (fat *)(myvhard + 3 * BLOCKSIZE);
root = (fcb *)(myvhard + 5 * BLOCKSIZE);
strcpy(blk0->magic, "10101010");
strcpy(blk0->information, "My FileSystem Ver 1.0 \n Blocksize=1KB Whole size=1000KB Blocknum=1000 RootBlocknum=2\n");
blk0->root = 5;
blk0->startblock = (unsigned char *)root;
for(i = 0; i < 5; i++)
{
fat1->id = END;
fat2->id = END;
fat1++;
fat2++;
}
fat1->id = 6;
fat2->id = 6;
fat1++;
fat2++;
fat1->id = END;
fat2->id = END;
fat1++;
fat2++;
for(i = 7; i < SIZE / BLOCKSIZE; i++)
{
fat1->id = FREE;
fat2->id = FREE;
fat1++;
展开阅读全文