模拟实现单级目录的FAT文件系统
了解计算机文件系统NTFSFAT和HFS的区别
了解计算机文件系统NTFSFAT和HFS的区别计算机文件系统是操作系统用来组织和管理计算机存储设备上的文件和目录的一种机制。
在不同的操作系统中,常见的文件系统有NTFS、FAT和HFS。
本文将就NTFS、FAT和HFS三种文件系统进行比较,以帮助大家更好地了解它们之间的区别。
一、NTFSNTFS(New Technology File System)是微软公司开发的一种高性能、可靠性和安全性较强的文件系统。
NTFS首次被引入Windows NT操作系统,并一直沿用至今。
1.1 文件系统结构NTFS采用了一种分层次的文件系统结构。
它包含了主引导记录(MBR)、分区表、文件记录、文件分配表等重要的组成部分。
而数据存储则是通过将文件分割成不同的簇来管理。
1.2 特点和功能NTFS具有许多先进的特点和功能,例如:- 安全性:NTFS支持访问控制列表(ACL)和文件加密,可以对文件和目录进行更细粒度的权限控制。
- 可靠性:NTFS采用了日志和冗余技术,使得文件系统更加稳定和可靠。
- 容量:NTFS最大支持16EB(1EB=1024PB)的存储容量,能够满足大容量存储的需求。
- 文件压缩和加密:NTFS支持文件压缩和加密,可以提高存储效率并保护敏感数据的安全性。
二、FATFAT(File Allocation Table)是一种较早的文件系统,最初是由微软开发的。
FAT文件系统广泛应用于早期的Windows操作系统和一些移动存储设备中。
2.1 文件系统结构FAT文件系统采用了一种比较简单的存储结构,它通过FAT表来管理文件和目录。
FAT表是一个记录簇号和下一个簇号之间对应关系的查找表。
2.2 特点和功能FAT文件系统具有以下特点和功能:- 简单易用:FAT文件系统结构简单,易于实现和维护。
- 兼容性好:FAT文件系统具有较好的兼容性,可以在不同操作系统之间进行文件共享和传输。
- 存储限制:FAT文件系统的文件大小限制为4GB,对于大容量存储设备来说可能不够满足需求。
解释什么是文件系统并介绍一下常见的文件系统
解释什么是文件系统并介绍一下常见的文件系统文件系统是计算机系统中用来管理和组织计算机存储设备上文件和目录的一种机制。
它通过一系列的算法和数据结构将文件和目录组织在存储设备上,并提供访问、读写、修改、删除等操作。
文件系统可以是硬件依赖的,也可以是独立于硬件的,在不同的操作系统中也可能有不同的实现方式。
一、文件系统的概念和作用文件系统是操作系统中的一个重要组成部分,它为用户和程序提供了一个统一的接口,使得用户能够方便地管理自己的文件和数据。
文件系统通过文件名、路径和索引等方式来唯一标识和定位文件,使得用户能够按照自己的需求轻松地组织和管理文件。
文件系统的作用主要有以下几个方面:1. 存储管理:文件系统负责将文件和目录存储在物理设备上,并管理存储空间的分配和释放,确保文件的完整性和可靠性。
2. 访问控制:文件系统通过对文件和目录的权限设置和访问控制列表,保护用户的数据安全,确保只有被授权的用户能够访问和修改文件。
3. 文件组织:文件系统提供了一种逻辑上的文件组织方式,如目录树结构、文件扩展名等,使得用户能够按照自己的需求进行文件的分类和组织。
4. 文件操作:文件系统提供了一系列的文件操作接口,如打开、关闭、读写、删除等,方便用户对文件进行各种操作。
二、常见的文件系统类型1. FAT文件系统:FAT(File Allocation Table)文件系统是由微软开发的一种常见的文件系统类型。
它包括FAT12、FAT16和FAT32等多个版本,主要用于MS-DOS、Windows 95/98、Windows ME等操作系统中。
FAT文件系统采用了简单的文件分配表来管理磁盘上的文件和空闲空间,具有兼容性好、速度快的特点,但对单个文件的最大大小和文件名的长度有一定限制。
2. NTFS文件系统:NTFS(New Technology File System)文件系统是微软开发的一种高级文件系统类型,用于Windows NT系列、Windows 2000/XP/7/8/10等操作系统中。
Fatfs文件系统2015-04
2015-04-18FATFS文件管理系统一、FATFS简介FATFS 是一个完全免费开源的FAT 文件系统模块,专门为小型的嵌入式系统而设计。
它完全用标准 C 语言编写,所以具有良好的硬件平台独立性,可以移植到8051、PIC、AVR、SH、Z80、H8、ARM 等系列单片机上而只需做简单的修改。
它支持FATl2、FATl6 和FAT32,支持多个存储媒介;有独立的缓冲区,可以对多个文件进行读/写,并特别对8 位单片机和16 位单片机做了优化。
FATFS 的特点有:✧ 代码量少、效率高✧ 多种配置选项✧ 支持多卷(物理驱动器或分区,最多10 个卷)✧ 多个ANSI/OEM 代码页包括DBCS✧ 支持长文件名、ANSI/OEM 或Unicode✧ 支持RTOS✧ 支持多种扇区大小✧ 只读、最小化的API 和I/O 缓冲区等二、FATFS层次结构图最顶层是应用层,使用者无需理会FATFS 的内部结构和复杂的FAT 协议,只需要调用FATFS 模块提供给用户的一系列应用接口函数,如f_open,f_read,f_write 和f_close 等,就可以像在PC 上读/写文件那样简单。
中间层FATFS 模块,实现了FAT 文件读/写协议。
FATFS 模块提供的是ff.c 和ff.h。
除非有必要,使用者一般不用修改,使用时将头文件直接包含进去即可。
需要我们编写移植代码的是FATFS 模块提供的底层接口,它包括存储媒介读/写接口(disk I/O)和供给文件创建修改时间的实时时钟。
三、FATFS源码1.源码下载(1)在/fsw/ff/00index_e.html下载FatFs源码R0.10b版本;(2)打开压缩包,里面有doc和src两个文件夹,doc是对FatFs的一些介绍及更新说明,src为FatFs的源码;2.FatFs源码介绍(1)与硬件平台无关的文件✧ffconf.h FATFS 模块配置文件✧ff.h FATFS 和应用模块公用的包含文件✧ff.c FATFS 模块✧diskio.h FATFS 和disk I/O 模块公用的包含文件✧interger.h 数据类型定义✧option 可选的外部功能(比如支持中文等)(2) 与硬件平台相关的文件✧diskio.c FATFS 和disk I/O 模块接口层文件(3) 移植时,重要的选项配置✧_FS_TINY。
FAT文件系统读写程序
经过一个多月的努力,终于完成了fat文件系统的读写函数。
期间由于过年,杂事较多,所以一再推迟。
起初是模仿zlgfs,但当写到一半时觉得这样构架很难写。
于是又返工,重新设计,十分郁闷。
到最后从中能找到zlgfs影子的地方也就是几个结构体而已。
虽然也有缓冲区,但其算法已经是比zlgfs复杂很多,是参考linux的缓冲区算法的,查找使用的是一个双向循环链表和一个hash表,弄了好久才把主要的bug除掉。
总之,主要就是实现了在fat16文件系统中的多级目录,及文件目录的读写,创建。
最后还写了一个文本文件的读写和bmp图片的读写,结合我以前在这个开发板上做的gui,实现了触摸屏显示24位bmp图片的功能。
我测试时,只要在sd卡上存储上24位bmp图片就可以在lcd上显示,十分方便。
其中包含fat文件系统读写程序在EasyFS目录中,此源代码是ads1.2工程,是在fs2410开发板上的。
点击此处下载ourdev_418380.rar(文件大小:3.75M)(原文件名:EasySystem_2. rar)点击此处下载 ourdev_612887.rar(文件大小:3.75M) (原文件名:EasySystem_2. rar)(原文件名:ourdev_596204.JPG)引用图片(原文件名:1--磁盘信息.jpg)这是在添加文件系统的磁盘驱动程序时在串口中打印的磁盘信息。
(原文件名:ourdev_612928.jpg)引用图片(原文件名:2.jpg)这是测试文件显示和创建,先在串口中打印文件"11111\\maomaob.txt",然后创建文件"mao\\shuang\\pei\\chengmao.txt",并向其中写入"mao mao cheng pe i"(原文件名:ourdev_612929.jpg)引用图片(原文件名:2--创建一个文本文件.jpg)(原文件名:ourdev_612930.jpg)引用图片(原文件名:3.jpg)这个上面的图标也是在存储在sd卡中的,其中左边和黑白条纹就是使用下面的这段代码创建的bmp图片。
FAT文件系统的组织结构
FAT文件系统的组织结构 1. 软盘数据的逻辑存储 软盘无须低级格式化和分区操作,只需用FORMAT命令做高级格式化即可。
经过格式化操作之 后,系统将在软磁盘上建立以下的数据结构: (1) 引导记录(DBR):位于0面0道1扇区,说明磁盘结构信息。
(2) 文件分配表(FAT):用于记录磁盘空间的分配情况,指示硬盘数据信息存 放的柱面及扇区的信息指针。
其表项可以是以下四种表示方式之一: A.一个数字,代表指向另一个簇的指针。
B.数字0,表示一个未使用的簇 C.一个坏扇区标记 D.文件结束标记符EOF (3) 文件根目录表FDT:一个指示以存入数据信息的索引。
记录磁盘上存储文 件的大小,位置,日期和时间等数据。
(4) 数据区:存放数据信息。
2. 硬盘中的数据组织 刚刚从厂商处购来的新硬盘既无任何数据,也不能写入任何数据,必须先进行低级格 式化,FDISK分区,FORMAT高级格式化后方可使用。
对硬盘的这一系列初始化工作,称之为 硬盘准备。
过程如下: 低级格式化---------------FDISK分区-------------------FORMAT高级格式化 (1)低级格式化:对硬盘划分磁道和扇区,在扇区的地址域上标注地址信息,并剔出坏磁 道。
(2)FDISK:允许整个物理硬盘在逻辑上划分成多个分区(最多4个),以实现多个操作系 统共享硬盘空间。
如果将整个物理盘全部划归DOS/WINDOWS管理,则FDISK分区的作用是将一 个物理盘划分一个主分区和一个扩展分区,然后再将扩展分区划分成一个或多个逻辑盘。
在 硬盘上建立分区表的同时,FDISK把主引导记录MBR写到硬盘的主引导记录(柱面0,磁头0, 扇区1),并激活一个用户指定的分区。
(3)FORMAT:在DOS分区空间划分逻辑扇区,生成DOS引导扇区(即逻辑0扇区)DBR,文件 分配表FAT和根文件目录表FDT。
硬盘在DOS/WINDOWS的管理下,数据信息由MBR,DBR,FAT,FDT和数据区5 个部分组成。
fat文件系统
FAT文件系统简介FAT(File Allocation Table)文件系统是一种广泛应用于计算机存储设备上的文件系统。
它最初在1977年由Microsoft开发,目前已经成为一种业界标准,被广泛支持使用。
FAT文件系统主要用于移动存储设备,如U盘、SD卡等。
它的设计简单、实现容易,占用资源较少,具有较好的兼容性和可移植性。
FAT文件系统支持在多个操作系统上读写数据,因此广泛应用于不同的设备和平台。
文件系统结构FAT文件系统由三个主要组成部分组成:文件分配表(File Allocation Table)、目录和文件数据区。
文件分配表(FAT)文件分配表是FAT文件系统的核心组成部分之一。
它记录了存储设备上每个文件的存储位置和状态。
FAT文件分配表以固定大小的簇为单位进行存储,每个簇的大小由文件系统的格式化参数决定。
文件分配表中的每个条目都对应一个簇,用于标记该簇的使用状态。
文件分配表通过链表的形式连接簇,形成文件的分配链。
通过遍历分配链,可以确定一个文件的存储位置和大小。
目录目录是FAT文件系统中用于存储文件和子目录信息的地方。
每个目录都有一个特定的条目用于描述该目录的属性和内容。
每个目录条目包含文件名、文件属性、创建日期等信息。
目录条目中还包含一个指向簇的条目,记录了文件或目录的起始簇号。
目录可以有多级,通过目录项中的指向上级目录的引用,可以在FAT文件系统中实现文件的层次结构。
文件数据区文件数据区是FAT文件系统中用于存储文件实际内容的地方。
它由一系列的簇组成,每个簇的大小由文件系统的格式化参数决定。
文件数据区通过文件分配表中的分配链来连接簇,形成文件的完整内容。
FAT文件系统的优缺点优点1.兼容性强:FAT文件系统可以在多个操作系统上读写数据,包括Windows、Linux、Mac等。
2.简单易用:FAT文件系统的设计简单,实现容易,易于开发和维护。
3.格式化兼容性好:FAT文件系统的格式化参数可以根据设备的特点进行调整,使之适应不同的存储介质。
文件系统fat和ntfs的原理
文件系统fat和ntfs的原理FAT和NTFS是两种常见的文件系统,它们在计算机存储中起着重要的作用。
本文将分别介绍FAT和NTFS的原理,以及它们在文件存储中的特点和应用。
一、FAT文件系统的原理FAT(File Allocation Table)文件系统是最早应用于个人计算机的一种文件系统。
它的原理是将存储设备(如硬盘、U盘等)划分为若干个簇(Cluster),每个簇由若干个扇区(Sector)组成。
FAT 文件系统通过使用文件分配表(File Allocation Table)来记录每个簇的使用情况,以便于管理文件的存储和检索。
在FAT文件系统中,文件和目录被组织为一个层次结构,最顶层是根目录(Root Directory),根目录下可以包含文件和子目录。
每个文件或目录的相关信息,如名称、大小、属性等,都存储在目录项(Directory Entry)中。
而目录项的内容则通过文件分配表来确定文件或目录所占用的簇的位置。
FAT文件系统的优点之一是兼容性强,几乎所有操作系统都能够识别和访问FAT格式的存储设备。
此外,FAT文件系统还具有简单、易于实现和维护的特点。
二、NTFS文件系统的原理NTFS(New Technology File System)文件系统是微软公司开发的一种高级文件系统,它首次引入于Windows NT操作系统。
相对于FAT文件系统,NTFS具有更多的功能和更好的性能。
NTFS文件系统的原理是将存储设备划分为一个个的簇,每个簇的大小可以根据实际需求进行调整。
与FAT不同的是,NTFS使用了一种称为MFT(Master File Table)的结构来管理文件和目录的存储。
在NTFS文件系统中,每个文件和目录都有一个唯一的MFT记录,该记录存储了文件的元数据(如文件名、大小、权限等)以及文件的数据存储位置。
MFT记录中的数据可以直接存储在记录本身中,也可以通过指针指向其他数据簇。
实现实时FAT文件系统的一种简单方法
Ab t a t M0 t e e d d mat d vc s n h ma k t o u e t e A f e y t m b c u e f i c mp t i t . w v r t e sr c : s mb d e s r e ie i t e r e n w s h F T i s se l e a s o t o ai l y Ho e e ,h s bi F wa n t e l e in d o AT s o w l d sg e t me t e l i r q i me t. h s ril p o o e a i l s l t n h t r al i r v s h e r a t me e u r e ns i T a t e r p s s smp e o ui t a g e t c o y mp o e t e r s o s i f t e AT f e s se wi o t u i g i o ai i t . ep ne t me o h F l y t m, t u h r n t c mp t ly i h t s bi Ke r s F y wo d : AT; l y tm ;e l t i fess e r a i me; o rs e AT;r e c u tr i d x c mp e s d F fe — l se n e
读写文件时文件系统经常需要进行文件逻辑簇号即这个文件中的第几个簇到物理簇号整个文件系统中的实际簇号的转换在这种链表结构中要进行这种转换必须对fat表进行遍历操作所以响应时间与读写位置呈线性关系时间复杂度为on其中n为要访问的数据所在的逻辑簇号
维普资讯
FAT文件系统操作系统课程设计实验报告
F A T文件系统操作系统课程设计实验报告集团标准化办公室:[VV986T-J682P28-JP266L8-68PNN]操作系统课程设计之三设计任务:模拟OS文件系统在任一OS(Window或者Dos;也可以是在Linux下,但要求能将结果演示给老师看)下,建立一个大文件,把它假象成一张盘,在其中实现一个简单的模拟OS文件系统。
1、在现有机器硬盘上开辟10M(共10000个盘块,每盘块大小为1k)的硬盘空间(生成一个10M的用户文件即可),作为设定的硬盘空间。
2、编写一管理程序SDisk,对此空间进行管理,以模拟OS文件系统,要求:⑴、盘块大小1k⑵、空闲盘块的管理:采用位示图法⑶、文件空间管理:采用FAT(文件分配表),每个盘块号占2个字节⑷、目录项管理:①、每个目录项占用32字节,其中前8个字节(0-7)为文件名,之后跟3个字节(8-10)的扩展名,26-27字节,存放文件的第一个盘块号,最后四个字节(28-31),存放文件长度(如果目录项对应的是下一级子目录(文件),其文件长度部分为0)②、目录按文件方式管理,每个目录仅用一个盘块(即1k,最多装32个目录项)③、第0个目录项为本目录,即“.”,第0个字节为“.”,即0x2E,第26-27字节指明本目录所在盘块。
④、第1个目录项为父目录,即“..”,第0,1个字节为“..”即0x2E,0x2E,第26-27字节指明父目录所在盘块。
⑤、每个目录实际能放下文件或子目录30项。
⑸、文件系统空间分配:①、第0个盘块(1k)存放磁盘信息(可以设定为格式说明“FAT32”、盘块大小,盘块数等内容)②、第1个盘块起,至125盘块,共125个盘块(125k)存放FAT内容③、第126、127(2个)盘块,存放位示图④、从第128盘块至10000盘块,皆为数据(区)盘块,其逻辑编号从0开始,至9872号数据盘块,即第0数据盘块为128号盘块,第1数据盘块为129号盘块,…⑤、第0数据盘块(即128号盘块),存放根目录(同样只用一个盘块作根目录),由于第0、1目录项为“.”(本目录), “..”(父目录),因此根目录下同样只能存放30个文件或目录,并且从第2个目录项开始。
虚拟文件系统的实现
实验六文件系统一、目的要求1、用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。
从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。
二、实验内容创建文件:创建一个新文件时,系统首先要为新文件申请必要的外存空间,并在FAT 中为文件分配一个目录项。
目录项中应记录新建文件的文件名、文件总容量、当前已经使用的容量、文件属性、文件在磁盘中的起始位置。
删除文件:当已不在需要某文件时,可将它从文件系统中删除。
在删除时,首先在FAT的文件链表中找到与该文件对应的文件结点,然后确认文件是否处于关闭状态,若以上条件都满足,则系统就可以把结点从文件链表中删除,然后回收改结点对应的磁盘空间。
打开文件:只有处于打开状态的文件才能被读取、写入、重复关闭且不能被删除。
关闭文件:只有处于关闭状态的文件才能被删除,且不能被重复关闭。
列文件目录:用户只能获取自己建立的文件或其他用户共享的文件的列表,并可以查看所用户建立的文件列表。
写文件:用户可以把相关数据写入到用户自定义的文件中(磁盘上);待写文件必须处于打开状态,且不能是其他用户共享的文件。
读文件:用户可以把文件中存储的数据读取出来;待读文件必须处于打开状态;用户既可以读取自己建立的文件,也可以读取其他用户共享的文件。
建子目录:输入目录名,若存在于该文件名相同的目录,这创建失败;若无,则查找空闲的磁盘,将该磁盘置为分配状态,填写目录项,分配地址后,子目录创建成功。
删除目录:输入名字,查找是否存在该文件或目录,若为文件,则不能删除;若存在,找到起始盘块号,并将其释放,修改目录项,删除成功。
附录主要代码源程序:#include<stdio.h>#include<string.h>#include<stdlib.h>#define MEM_D_SIZE 1024*1024 //总磁盘空间为M#define DISKSIZE 1024 //磁盘块的大小K#define DISK_NUM 1024 //磁盘块数目K#define FATSIZE DISK_NUM*sizeof(struct fatitem) //FAT表大小#define ROOT_DISK_NO FATSIZE/DISKSIZE+1 //根目录起始盘块号#define ROOT_DISK_SIZE sizeof(struct direct) //根目录大小#define DIR_MAXSIZE 1024 //路径最大长度为KB#define MSD 5 //最大子目录数#define MOFN 5 //最大文件深度为#define MAX_WRITE 1024*128 //最大写入文字长度KBstruct fatitem /* size 8*/{int item; /*存放文件下一个磁盘的指针*/char em_disk; /*磁盘块是否空闲标志位0 空闲*/};struct direct{/*-----文件控制快信息-----*/struct FCB{char name[9]; /*文件/目录名8位*/char property; /*属性1位目录0位普通文件*/int size; /*文件/目录字节数、盘块数)*/int firstdisk; /*文件/目录起始盘块号*/int next; /*子目录起始盘块号*/int sign; /*1是根目录0不是根目录*/}directitem[MSD+2];};struct opentable{struct openttableitem{char name[9]; /*文件名*/int firstdisk; /*起始盘块号*/int size; /*文件的大小*/}openitem[MOFN];int cur_size; /*当前打文件的数目*/};struct fatitem *fat; /*FAT表*/struct direct *root; /*根目录*/struct direct *cur_dir; /*当前目录*/struct opentable u_opentable; /*文件打开表*/int fd=-1; /*文件打开表的序号*/char *bufferdir; /*记录当前路径的名称*/char *fdisk; /*虚拟磁盘起始地址*/void initfile();void format();void enter();void halt();int create(char *name);int open(char *name);int close(char *name);int write(int fd,char *buf,int len);int read(int fd,char *buf);int del(char *name);int mkdir(char *name);int rmdir(char *name);void dir();int cd(char *name);void print();void show();void initfile(){fdisk = (char *)malloc(MEM_D_SIZE*sizeof(char)); /*申请1M空间*/format();}void format(){int i;FILE *fp;fat = (struct fatitem *)(fdisk+DISKSIZE); /*计算FAT表地址,引导区向后偏移1k)*/ /*-----初始化FAT表------------*/fat[0].item=-1; /*引导块*/fat[0].em_disk='1';for(i=1;i<ROOT_DISK_NO-1;i++) /*存放FAT表的磁盘块号*/{fat[i].item=i+1;fat[i].em_disk='1';}fat[ROOT_DISK_NO].item=-1; /*存放根目录的磁盘块号*/fat[ROOT_DISK_NO].em_disk='1';for(i=ROOT_DISK_NO+1;i<DISK_NUM;i++){fat[i].item = -1;fat[i].em_disk = '0';}/*-----------------------------------------------*/root = (struct direct *)(fdisk+DISKSIZE+FATSIZE); /*根目录的地址*/ /*初始化目录*//*---------指向当前目录的目录项---------*/root->directitem[0].sign = 1;root->directitem[0].firstdisk = ROOT_DISK_NO;strcpy(root->directitem[0].name,".");root->directitem[0].next = root->directitem[0].firstdisk;root->directitem[0].property = '1';root->directitem[0].size = ROOT_DISK_SIZE;/*-------指向上一级目录的目录项---------*/root->directitem[1].sign = 1;root->directitem[1].firstdisk = ROOT_DISK_NO;strcpy(root->directitem[1].name,"..");root->directitem[1].next = root->directitem[0].firstdisk;root->directitem[1].property = '1';root->directitem[1].size = ROOT_DISK_SIZE;if((fp = fopen("disk.dat","wb"))==NULL){printf("Error:\n Cannot open file \n");return;}for(i=2;i<MSD+2;i++) /*-子目录初始化为空-*/{root->directitem[i].sign = 0;root->directitem[i].firstdisk = -1;strcpy(root->directitem[i].name,"");root->directitem[i].next = -1;root->directitem[i].property = '0';root->directitem[i].size = 0;}if((fp = fopen("disk.dat","wb"))==NULL){printf("Error:\n Cannot open file \n");return;}if(fwrite(fdisk,MEM_D_SIZE,1,fp)!=1) /*把虚拟磁盘空间保存到磁盘文件中*/{printf("Error:\n File write error! \n");}fclose(fp);}void enter(){FILE *fp;int i;fdisk = (char *)malloc(MEM_D_SIZE*sizeof(char)); /*申请1M空间*/if((fp=fopen("disk.dat","rb"))==NULL){printf("Error:\nCannot open file\n");return;}if(!fread(fdisk,MEM_D_SIZE,1,fp)) /*把磁盘文件disk.dat 读入虚拟磁盘空间(内存)*/ {printf("Error:\nCannot read file\n");exit(0);}fat = (struct fatitem *)(fdisk+DISKSIZE); /*找到FAT表地址*/root = (struct direct *)(fdisk+DISKSIZE+FATSIZE);/*找到根目录地址*/fclose(fp);/*--------------初始化用户打开表------------------*/for(i=0;i<MOFN;i++){strcpy(u_opentable.openitem[i].name,"");u_opentable.openitem[i].firstdisk = -1;u_opentable.openitem[i].size = 0;}u_opentable.cur_size = 0;cur_dir = root; /*当前目录为根目录*/bufferdir = (char *)malloc(DIR_MAXSIZE*sizeof(char));strcpy(bufferdir,"Root:");}void halt(){FILE *fp;int i;if((fp=fopen("disk.dat","wb"))==NULL){printf("Error:\nCannot open file\n");return;}if(!fwrite(fdisk,MEM_D_SIZE,1,fp)) /*把虚拟磁盘空间(内存)内容读入磁盘文件disk.dat */ {printf("Error:\nFile write error!\n");}fclose(fp);free(fdisk);free(bufferdir);return;}int create(char *name){int i,j;if(strlen(name)>8) /*文件名大于8位*/return(-1);for(j=2;j<MSD+2;j++) /*检查创建文件是否与已存在的文件重名*/{if(!strcmp(cur_dir->directitem[j].name,name))break;}if(j<MSD+2) /*文件已经存在*/return(-4);for(i=2;i<MSD+2;i++) /*找到第一个空闲子目录*/{if(cur_dir->directitem[i].firstdisk==-1)break;}if(i>=MSD+2) /*无空目录项*/return(-2);if(u_opentable.cur_size>=MOFN) /*打开文件太多*/return(-3);for(j=ROOT_DISK_NO+1;j<DISK_NUM;j++) /*找到空闲盘块j 后退出*/ {if(fat[j].em_disk=='0')break;}if(j>=DISK_NUM)return(-5);fat[j].em_disk = '1'; /*将空闲块置为已经分配*//*-----------填写目录项-----------------*/strcpy(cur_dir->directitem[i].name,name);cur_dir->directitem[i].firstdisk = j;cur_dir->directitem[i].size = 0;cur_dir->directitem[i].next = j;cur_dir->directitem[i].property = '0';/*---------------------------------*/fd = open(name);return 0;}int open(char *name){int i, j;for(i=2;i<MSD+2;i++) /*文件是否存在*/{if(!strcmp(cur_dir->directitem[i].name,name))break;}if(i>=MSD+2)return(-1);/*--------是文件还是目录-----------------------*/if(cur_dir->directitem[i].property=='1')return(-4);/*--------文件是否打开-----------------------*/for(j=0;j<MOFN;j++){if(!strcmp(u_opentable.openitem[j].name,name))break;}if(j<MOFN) /*文件已经打开*/return(-2);if(u_opentable.cur_size>=MOFN) /*文件打开太多*/return(-3);/*--------查找一个空闲用户打开表项-----------------------*/for(j=0;j<MOFN;j++){if(u_opentable.openitem[j].firstdisk==-1)break;}/*--------------填写表项的相关信息------------------------*/u_opentable.openitem[j].firstdisk = cur_dir->directitem[i].firstdisk;strcpy(u_opentable.openitem[j].name,name);u_opentable.openitem[j].size = cur_dir->directitem[i].size;u_opentable.cur_size++;/*----------返回用户打开表表项的序号--------------------------*/return(j);}int close(char *name){int i;for(i=0;i<MOFN;i++){if(!strcmp(u_opentable.openitem[i].name,name))break;}if(i>=MOFN)return(-1);/*-----------清空该文件的用户打开表项的内容---------------------*/ strcpy(u_opentable.openitem[i].name,"");u_opentable.openitem[i].firstdisk = -1;u_opentable.openitem[i].size = 0;u_opentable.cur_size--;return 0;}int write(int fd, char *buf, int len){char *first;int item, i, j, k;int ilen1, ilen2, modlen, temp;/*----------用$ 字符作为空格# 字符作为换行符-----------------------*/char Space = 32;char Endter= '\n';for(i=0;i<len;i++){if(buf[i] == '$')buf[i] = Space;else if(buf[i] == '#')buf[i] = Endter;}/*----------读取用户打开表对应表项第一个盘块号-----------------------*/ item = u_opentable.openitem[fd].firstdisk;/*-------------找到当前目录所对应表项的序号-------------------------*/for(i=2;i<MSD+2;i++){if(cur_dir->directitem[i].firstdisk==item)break;}temp = i; /*-存放当前目录项的下标-*//*------找到的item 是该文件的最后一块磁盘块-------------------*/while(fat[item].item!=-1){item =fat[item].item; /*-查找该文件的下一盘块--*/}/*-----计算出该文件的最末地址-------*/first = fdisk+item*DISKSIZE+u_opentable.openitem[fd].size%DISKSIZE;/*-----如果最后磁盘块剩余的大小大于要写入的文件的大小-------*/if(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE>len){strcpy(first,buf);u_opentable.openitem[fd].size = u_opentable.openitem[fd].size+len;cur_dir->directitem[temp].size = cur_dir->directitem[temp].size+len;}else{for(i=0;i<(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE);i++){/*写一部分内容到最后一块磁盘块的剩余空间(字节)*/first[i] = buf [i];}/*-----计算分配完最后一块磁盘的剩余空间(字节) 还剩下多少字节未存储-------*/ ilen1 = len-(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE);ilen2 = ilen1/DISKSIZE;modlen = ilen1%DISKSIZE;if(modlen>0)ilen2 = ilen2+1; /*--还需要多少块磁盘块-*/for(j=0;j<ilen2;j++){for(i=ROOT_DISK_NO+1;i<DISK_NUM;i++)/*寻找空闲磁盘块*/{if(fat[i].em_disk=='0')break;}if(i>=DISK_NUM) /*--如果磁盘块已经分配完了-*/return(-1);first = fdisk+i*DISKSIZE; /*--找到的那块空闲磁盘块的起始地址-*/if(j==ilen2-1) /*--如果是最后要分配的一块-*/{for(k=0;k<len-(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE)-j*DISKSIZE;k++) first[k] = buf[k];}else/*-如果不是要最后分配的一块--*/{for(k=0;k<DISKSIZE;k++)first[k] =buf[k];}fat[item].item = i; /*--找到一块后将它的序号存放在上一块的指针中-*/fat[i].em_disk = '1'; /*--置找到的磁盘快的空闲标志位为已分配-*/fat[i].item = -1; /*--它的指针为-1 (即没有下一块)-*/ }/*--修改长度-*/u_opentable.openitem[fd].size = u_opentable.openitem[fd].size+len;cur_dir->directitem[temp].size = cur_dir->directitem[temp].size+len;}return 0;}int read(int fd, char *buf){int len = u_opentable.openitem[fd].size;char *first;int i, j, item;int ilen1, modlen;item = u_opentable.openitem[fd].firstdisk;ilen1 = len/DISKSIZE;modlen = len%DISKSIZE;if(modlen!=0)ilen1 = ilen1+1; /*--计算文件所占磁盘的块数-*/first = fdisk+item*DISKSIZE; /*--计算文件的起始位置-*/for(i=0;i<ilen1;i++){if(i==ilen1-1) /*--如果在最后一个磁盘块-*/{for(j=0;j<len-i*DISKSIZE;j++)buf[i*DISKSIZE+j] = first[j];}else /*--不在最后一块磁盘块-*/{for(j=0;j<len-i*DISKSIZE;j++)buf[i*DISKSIZE+j] = first[j];item = fat[item].item; /*-查找下一盘块-*/first = fdisk+item*DISKSIZE;}}return 0;}int del(char *name){int i,cur_item,item,temp;for(i=2;i<MSD+2;i++) /*--查找要删除文件是否在当前目录中-*/{if(!strcmp(cur_dir->directitem[i].name,name))break;}cur_item = i; /*--用来保存目录项的序号,供释放目录中-*/if(i>=MSD+2) /*--如果不在当前目录中-*/return(-1);if(cur_dir->directitem[cur_item].property!='0') /*--如果删除的(不)是目录-*/ return(-3);for(i=0;i<MOFN;i++) /*--如果文件打开,则不能删除,退出-*/{if(!strcmp(u_opentable.openitem[i].name,name))return(-2);}item = cur_dir->directitem[cur_item].firstdisk;/*--该文件的起始盘块号-*/ while(item!=-1) /*--释放空间,将FAT表对应项进行修改-*/{temp = fat[item].item;fat[item].item = -1;fat[item].em_disk = '0';item = temp;}/*-----------------释放目录项-----------------------*/cur_dir->directitem[cur_item].sign = 0;cur_dir->directitem[cur_item].firstdisk = -1;strcpy(u_opentable.openitem[cur_item].name,"");cur_dir->directitem[cur_item].next = -1;cur_dir->directitem[cur_item].property = '0';cur_dir->directitem[cur_item].size = 0;return 0;}int mkdir(char *name){int i,j;struct direct *cur_mkdir;if(!strcmp(name,"."))return(-4);if(!strcmp(name,".."))return(-4);if(strlen(name)>8) /*-如果目录名长度大于8位-*/return(-1);for(i=2;i<MSD+2;i++) /*-如果有空闲目录项退出-*/{if(cur_dir->directitem[i].firstdisk==-1)break;}if(i>=MSD+2) /*-目录/文件已满-*/return(-2);for(j=2;j<MSD+2;j++) /*-判断是否有重名-*/{if(!strcmp(cur_dir->directitem[j].name,name))break;}if(j<MSD+2) /*-如果有重名-*/return(-3);for(j=ROOT_DISK_NO+1;j<DISK_NUM;j++) /*-找到空闲磁盘块j 后退出-*/ {if(fat[j].em_disk=='0')break;}if(j>=DISK_NUM)return(-5);fat[j].em_disk='1'; /*-将该空闲块设置为已分配-*//*-------------填写目录项----------*/strcpy(cur_dir->directitem[i].name,name);cur_dir->directitem[i].firstdisk=j;cur_dir->directitem[i].size=ROOT_DISK_SIZE;cur_dir->directitem[i].next=j;cur_dir->directitem[i].property='1';/*-所创目录在虚拟磁盘上的地址(内存物理地址)-*/cur_mkdir=(struct direct *)(fdisk+cur_dir->directitem[i].firstdisk*DISKSIZE); /*-初始化目录-*//*-指向当前目录的目录项-*/cur_mkdir->directitem[0].sign=0;cur_mkdir->directitem[0].firstdisk=cur_dir->directitem[i].firstdisk;strcpy(cur_mkdir->directitem[0].name,".");cur_mkdir->directitem[0].next=cur_mkdir->directitem[0].firstdisk;cur_mkdir->directitem[0].property='1';cur_mkdir->directitem[0].size=ROOT_DISK_SIZE;/*-指向上一级目录的目录项-*/cur_mkdir->directitem[1].sign=cur_dir->directitem[0].sign;cur_mkdir->directitem[1].firstdisk=cur_dir->directitem[0].firstdisk;strcpy(cur_mkdir->directitem[1].name,"..");cur_mkdir->directitem[1].next=cur_mkdir->directitem[1].firstdisk;cur_mkdir->directitem[1].property='1';cur_mkdir->directitem[1].size=ROOT_DISK_SIZE;for(i=2;i<MSD+2;i++) /*-子目录都初始化为空-*/{cur_mkdir->directitem[i].sign=0;cur_mkdir->directitem[i].firstdisk=-1;strcpy(cur_mkdir->directitem[i].name,"");cur_mkdir->directitem[i].next=-1;cur_mkdir->directitem[i].property='0';cur_mkdir->directitem[i].size=0;}return 0;}int rmdir(char *name){int i,j,item;struct direct *temp_dir;/*-检查当前目录项中有无该目录-*/for(i=2;i<MSD+2;i++){if(!strcmp(cur_dir->directitem[i].name,name))break;}if(i>=MSD+2) /*-没有这个文件或目录-*/return(-1);if(cur_dir->directitem[i].property!='1')/*-删除的不是目录-*/ return(-3);/*-判断要删除的目录有无子目录-*/temp_dir=(struct direct *)(fdisk+cur_dir->directitem[i].next*DISKSIZE);for(j=2;j<MSD+2;j++){if(temp_dir->directitem[j].next!=-1)break;}if(j<MSD+2) /*-有子目录或文件-*/return(-2);/*------------找到起始盘块号,并将其释放----------------*/item=cur_dir->directitem[i].firstdisk;fat[item].em_disk='0';/*-修改目录项-*/cur_dir->directitem[i].sign=0;cur_dir->directitem[i].firstdisk=-1;strcpy(cur_dir->directitem[i].name,"");cur_dir->directitem[i].next=-1;cur_dir->directitem[i].property='0';cur_dir->directitem[i].size=0;return 0;}void dir(){int i;for(i=2;i<MSD+2;i++){if(cur_dir->directitem[i].firstdisk!=-1) /*-如果存在子目录-*/{printf("%s\t",cur_dir->directitem[i].name);if(cur_dir->directitem[i].property=='0') /*-文件-*/printf("%d\t\t\n",cur_dir->directitem[i].size);elseprintf("\t<目录>\t\n");}}}int cd(char *name){int i,j,item;char *str;char *temp,*point,*point1;struct direct *temp_dir;temp_dir=cur_dir;str=name;if(!strcmp("\\",name)){cur_dir = root;strcpy(bufferdir,"Root:");return 0;}temp = (char *)malloc(DIR_MAXSIZE*sizeof(char));/*-最长路径名字分配空间-*/for(i=0;i<(int)strlen(str);i++)temp[i]=str[i];temp[i]='\0';for(j=0;j<MSD+2;j++) /*-查找该子目录是否在当前目录中-*/{if(!strcmp(temp_dir->directitem[j].name,temp))break;}free(temp);/*释放申请的临时空间*///if(temp_dir->directitem[j].property!='1') /*-打开的不是目录-*///return(-2);if(j>=MSD+2) /*-不在当前目录-*/return(-1);item=temp_dir->directitem[j].firstdisk;/*-当前目录在磁盘中位置-*/temp_dir=(struct direct *)(fdisk+item*DISKSIZE);if(!strcmp("..",name)){if(cur_dir->directitem[j-1].sign!=1) /*-如果上级目录不是根目录-*/{point=strchr(bufferdir,'\\'); //查找字符串bufferdir中首次出现字符\ 的位置while(point!=NULL){point1=point+1; /*-减去'\'所占的空间,记录下次查找的起始地址-*/point=strchr(point1,'\\');}*(point1-1)='\0'; /*-将上一级目录删除-*/}}else{//if(name[0] !='\\')bufferdir = strcat(bufferdir,"\\"); /*-修改当前目录-*/bufferdir = strcat(bufferdir,name);}cur_dir=temp_dir; /*-将当前目录确定下来-*/return 0;}void show(){printf("%s>",bufferdir);}void print(){printf("*********************************************************\n");printf("**********************文件系统设计***********************\n");printf("*\t命令格式说明*\n");printf("*\tcd 目录名更改当前目录*\n");printf("*\tmkdir 目录名创建子目录*\n");printf("*\trmdir 目录名删除子目录*\n");printf("*\tdir 显示当前目录的子目录*\n");printf("*\tcreate 文件名创建文件*\n");printf("*\tdel 文件名删除文件*\n");printf("*\topen 文件名打开文件*\n");printf("*\tclose 文件名关闭文件*\n");printf("*\tread 读文件*\n");printf("*\twrite 写文件*\n");printf("*\texit 退出系统*\n");printf("*********************************************************\n"); }main(){FILE *fp;char ch;char a[100];char code[11][10];char name[10];int i,flag,r_size;char *contect;contect = (char *)malloc(MAX_WRITE*sizeof(char));if((fp=fopen("disk.dat","rb"))==NULL){printf("You have not format,Do you want format?(y/n)");scanf("%c",&ch);if(ch=='y'){initfile();printf("Successfully format! \n");}else{return 0;}}enter();print();show();strcpy(code[0],"exit");strcpy(code[1],"create");strcpy(code[2],"open");strcpy(code[3],"close");strcpy(code[4],"write");strcpy(code[5],"read");strcpy(code[6],"del");strcpy(code[7],"mkdir");strcpy(code[8],"rmdir");strcpy(code[9],"dir");strcpy(code[10],"cd");while(1){scanf("%s",a);for(i=0;i<11;i++){if(!strcmp(code[i],a))break;}switch(i){case 0: //退出文件系统free(contect);halt();return 0;case 1: //创建文件scanf("%s",name);flag = create(name);if(flag==-1){printf("Error: \n The length is too long !\n");}else if(flag==-2){printf("Error: \n The direct item is already full !\n");}else if(flag==-3){printf("Error: \n The number of openfile is too much !\n");}else if(flag==-4){printf("Error: \n The name is already in the direct !\n");}else if(flag==-5){printf("Error: \n The disk space is full!\n");}else{printf("Successfully create a file! \n");}show();break;case 2://打开文件scanf("%s",name);fd = open(name);if(fd == -1){printf("Error: \n The open file not exit! \n");}else if(fd == -2){printf("Error: \n The file have already opened! \n");}else if(fd == -3){printf("Error: \n The number of open file is too much! \n");}else if(fd == -4){printf("Error: \n It is a direct,can not open for read or write! \n");}else{printf("Successfully opened! \n");}show();break;case 3://关闭文件scanf("%s",name);flag = close(name);if(flag == -1){printf("Error:\n The file is not opened ! \n");}else{printf("Successfully closed! \n");}show();break;case 4://写文件if(fd ==-1){printf("Error:\n The file is not opened ! \n");}elseprintf("Please input the file contect:");scanf("%s",contect);flag=write(fd,contect,strlen(contect));if(flag == 0){printf("Successfully write! \n");}else{printf("Error:\n The disk size is not enough! \n");}}show();break;case 5://读文件if(fd ==-1){printf("Error:\n The file is not opened ! \n");}else{flag = read(fd,contect);if(flag == 0){for(i=0;i<u_opentable.openitem[fd].size;i++){printf("%c",contect[i]);}printf("\t\n");}}show();break;case 6://删除文件scanf("%s",name);flag = del(name);if(flag == -1){printf("Error:\n The file not exit! \n");}else if(flag == -2)printf("Error:\n The file is opened,please first close it ! \n");}else if(flag == -3){printf("Error:\n The delete is not file ! \n");}else{printf("Successfully delete! \n");}show();break;case 7://创建子目录scanf("%s",name);flag = mkdir(name);if(flag == -1){printf("Error:\n The length of name is to long! \n");}else if(flag == -2){printf("Error:\n The direct item is already full ! \n");}else if(flag == -3){printf("Error:\n The name is already in the direct ! \n");}else if(flag == -4){printf("Error: \n '..' or '.' can not as the name of the direct!\n");}else if(flag == -5){printf("Error: \n The disk space is full!\n");}else if(flag == 0){printf("Successfully make dircet! \n");}show();break;case 8://删除子目录scanf("%s",name);flag = rmdir(name);if(flag == -1){printf("Error:\n The direct is not exist! \n");}else if(flag == -2){printf("Error:\nThe direct has son direct ,please first remove the son dircct!\n");}else if(flag == -3){printf("Error:\n The remove is not direct ! \n");}else if(flag == 0){printf("Successfully remove dircet! \n");}show();break;case 9://显示当前子目录dir();show();break;case 10://更改当前目录scanf("%s",name);flag = cd(name);if(flag == -1){printf("Error:\n The path no correct!\n");}else if(flag == -2){printf("Error:\nThe opened is not direct!\n");}show();break;default:printf("\n Error!\n The command is wrong! \n");show();}}}。
FAT文件系统原理 四 转载12页word
FAT文件系统原理四转载FAT文件系统原理(四)(转载)2011/06/12 10:18FAT文件系统原理(四)★FAT16存储原理:当把一部分磁盘空间格式化为fat文件系统时,fat文件系统就将这个分区当成整块可分配的区域进行规划,以便于数据的存储。
一般来讲,其划分形式如图7所示。
我们把FAT16部分提取出来,详细描述一下:FAT16是Microsoft较早推出的文件系统,具有高度兼容性,目前仍然广泛应用于个人电脑尤其是移动存储设备中,FAT16简单来讲由图4.3.11所示的6部分组成(主要是前5部分)。
引导扇区(DBR)我们已经说过,FAT16在DBR之后没有留有任何保留扇区,其后紧随的便是FAT 表。
FAT表是FAT16用来记录磁盘数据区簇链结构的。
像前面我们说过的例子一样,FAT将磁盘空间按一定数目的扇区为单位进行划分,这样的单位称为簇。
通常情况下,每扇区512字节的原则是不变的。
簇的大小一般是2n(n为整数)个扇区的大小,像512B,1K,2K,4K,8K,16K,32K,64K。
实际中通常不超过32K。
之所以簇为单位而不以扇区为单位进行磁盘的分配,是因为当分区容量较大时,采用大小为512b的扇区管理会增加fat表的项数,对大文件存取增加消耗,文件系统效率不高。
分区的大小和簇的取值是有关系的,见表9(单击此处查看PDF版全文)图4.3.11 Fat16的组织形式引导扇区FAT1 FAT2(重复的)根文件夹其他文件夹及所有文件剩余扇区1扇区实际情况取大小同FAT1 32个扇区开始簇编号(从2开始)不足一簇表9 FAT16分区大小与对因簇大小分区空间大小每个簇的扇区簇空间大小0MB-32MB 1512个字节33MB-64MB 21k 65MB-128MB 42k 129MB-225MB 84k 256MB-511MB 16 8k 512MB-1023MB 32 16k 1024MB-2047MB 64 32k 2048MB-4095MB 128 64k注意:少于32680个扇区的分区中,簇空间大小可最多达到每个簇8个扇区。
FAT文件系统原理
硬盘 FAT 文件系统原理的详细分析一、硬盘的物理结构: 硬盘的物理结构:硬盘存储数据是根据电、磁转换原理实现的。
硬盘由一个或几个表面镀有磁性物质 的金属或玻璃等物质盘片以及盘片两面所安装的磁头和相应的控制电路组成(图 1), 其中盘 片和磁头密封在无尘的金属壳中。
硬盘工作时,盘片以设计转速高速旋转,设置在盘片表面的磁头则在电路控制下径 向移动到指定位置然后将数据存储或读取出来。
当系统向硬盘写入数据时,磁头中“写数据” 电流产生磁场使盘片表面磁性物质状态发生改变, 并在写电流磁场消失后仍能保持, 这样数 据就存储下来了;当系统从硬盘中读数据时,磁头经过盘片指定区域,盘片表面磁场使磁头 产生感应电流或线圈阻抗产生变化, 经相关电路处理后还原成数据。
因此只要能将盘片表面 处理得更平滑、磁头设计得更精密以及尽量提高盘片旋转速度,就能造出容量更大、读写数 据速度更快的硬盘。
这是因为盘片表面处理越平、转速越快就能越使磁头离盘片表面越近, 提高读、写灵敏度和速度;磁头设计越小越精密就能使磁头在盘片上占用空间越小,使磁头 在一张盘片上建立更多的磁道以存储更多的数据。
二、硬盘的逻辑结构: 硬盘的逻辑结构: 硬盘由很多盘片(platter)组成,每个盘片的每个面都有一个读写磁头。
如果有 N 个盘片。
就有 2N 个面,对应 2N 个磁头(Heads),从 0、1、2 开始编号。
每个盘片被划 分成若干个同心圆磁道(逻辑上的,是不可见的。
)每个盘片的划分规则通常是一样的。
这样 每个盘片的半径均为固定值 R 的同心圆再逻辑上形成了一个以电机主轴为轴的柱面(Cylind ers), 从外至里编号为 0、 2……每个盘片上的每个磁道又被划分为几十个扇区(Sector), 1、 通常的容量是 512byte,并按照一定规则编号为 1、2、3……形成 Cylinders×Heads×S ector 个扇区。
虚拟文件系统的实现-FAT方案
虚拟文件系统的实现-FAT方案摘要: 本文简单介绍了磁盘文件格式FA T及其他相关背景和算法,并采用FA T方案实现单卷、单级目录的虚拟文件系统。
描述了整个程序的基本思路模块划分、流程图及代码的实现。
主题词: 文件文件系统FA T 虚拟磁盘真实磁盘一.相关背景1.1 相关概念,相关算法文件是操作系统提供的、在用户观点中其内容具有连续顺序关系的最大外存逻辑数据空间。
文件系统是操作系统提供的实现对外存文件的管理。
文件系统内部实现的主要区别有:单级目录或多级目录、单卷或多卷、连续分配或不连续分配。
在不连续分配的背景下主要有链接定位方式下的文件内地址映射机制和索引定位。
FAT(file allocation table)采用“文件分配表”方式,是链接定位技术的一个重要变种。
1.2 设计环境、设计工具整个程序采用C语言在Windows XP下使用Microsoft V isual 2003进行设计。
二.设计思路和总体流程图2.1基本思路整个磁盘采用单卷、单级目录FA T方案,在真实磁盘建立一个文件作,并根据用户要求的大小申请空间,实现基本的磁盘文件操作。
例如对文件进行建立、复制、浏览、重命名等操作。
并能够对虚拟磁盘进行格式化,能够与真实磁盘进行文件交换。
整个虚拟文件系统是一个可以使用的文件系统,里面存放的文件信息都是真实有效的,管理程序可以管理多个虚拟文件系统。
2.2 本系统支持的主要命令del 删除文件 format 格式化虚拟磁盘dir 显示文件信息 help 显示帮助cat 显示文件内容 icopy 真实磁盘向虚拟磁盘拷贝copy 虚拟磁盘内拷贝 ocopy 虚拟磁盘向真实磁盘拷贝exit 退出 rename 文件重命名fatinfo 显示FAT表内容 showdisk 显示虚拟磁盘信息2.3 数据结构定义FCB //文件控制块//char name[13]; //文件名//int startblock; //起始块//long size; //文件大小//int status; //FCB状态//DISKunsigned long disksize; //磁盘大小//unsigned int blocksize; //块长4096//unsigned int blocks; //总块数//unsigned int FATblocks; //FAT块数1-32//unsigned int dirblocks; //目录区块数33-34 //unsigned int datablocks; //文件数据区块数//unsigned int idleblocks; //空闲块数//unsigned int files; //文件数//unsigned long freesize; //可用空间//unsigned int realfiles; //有效文件数//unsigned int fcbsnum; //最大目录数//FATint fats;DISKINFODISK disk;FCB *fcbs;FAT *fat;2.4 虚拟磁盘总貌图1.1所示为虚拟磁盘总貌,盘卷总信息存放DISK结构体,FAT表区存放FAT结构体,目录区存放FCB结构体。
fat文件系统原理
fat文件系统原理FAT文件系统原理一、引言FAT(File Allocation Table)文件系统是一种用于存储和组织文件数据的文件系统。
它最早由Microsoft开发用于DOS操作系统,现已广泛应用于各种存储媒体中,如硬盘、U盘和存储卡等。
本文将介绍FAT文件系统的原理和工作机制。
二、FAT文件系统结构FAT文件系统由三个主要组成部分构成:引导扇区、文件分配表(FAT)和文件目录。
1. 引导扇区:FAT文件系统的第一个扇区是引导扇区,它包含了启动计算机时所需的引导代码。
引导扇区还包含了FAT文件系统的一些关键参数,如扇区大小、簇大小和FAT表的起始位置等。
2. 文件分配表(FAT):FAT是FAT文件系统的核心部分,用于记录文件在存储设备上的存储位置。
每个簇在FAT中都有一项对应,记录了该簇的状态和下一个簇的编号。
FAT的结构和大小取决于存储设备的容量,较小的设备可能只有一个FAT,而较大的设备则可能有多个FAT。
3. 文件目录:文件目录是FAT文件系统用于存储文件和文件夹信息的地方。
每个文件目录项包含了文件名、文件属性、文件大小和起始簇号等信息。
文件目录采用树状结构组织,通过文件目录项中的指针可以找到文件的具体位置。
三、FAT文件系统的工作原理FAT文件系统的工作原理可以概括为以下几个步骤:1. 引导过程:计算机启动时,BIOS会加载引导扇区的代码到内存中并执行,引导扇区的代码会读取FAT表的位置和大小等信息,并将控制权传递给操作系统。
2. FAT表的读取:操作系统根据引导扇区中的信息找到FAT表的位置,并将其读取到内存中。
FAT表可以告诉操作系统每个簇的使用状态和下一个簇的编号,从而实现文件的连续存储和读取。
3. 文件的查找和读取:当用户请求读取某个文件时,操作系统会根据文件目录进行查找,并获取文件的起始簇号。
然后,操作系统通过读取FAT表中的项,找到文件的所有簇号,并按顺序读取簇中的数据。
FAT文件系统原理
FAT文件系统原理FAT(File Allocation Table)文件系统是一种用于磁盘存储的文件系统。
它最早由微软公司在1977年为MS-DOS操作系统开发,后来被广泛应用于各种操作系统和设备中,如Windows、Linux、移动设备等。
FAT文件系统的原理主要包括文件和目录的组织方式、文件存储的分配方式、文件的访问和管理等方面。
FAT文件系统使用一种层次化的目录结构来组织文件和目录。
整个文件系统的入口是根目录,根目录下可以包含文件和子目录。
每个文件和目录都有一个唯一的文件名,它由一个主文件名和一个扩展名组成。
文件和目录之间的关系通过目录项来表示,每个目录项包含文件名、文件属性、文件大小、起始簇号等信息。
通过递归查找目录项,可以实现文件和目录的定位和访问。
FAT文件系统中,磁盘被分成多个连续的数据区块,每个数据区块称为一个簇。
簇是文件存储的最小单位,文件可以占用一个或多个簇。
在FAT表中,每个簇都有一个对应的表项,用于表示该簇的状态和下一个簇的编号。
FAT表是一个二维表格,每行代表一个簇,每列表示该簇的状态。
通过FAT表,可以查找文件的簇链,实现文件的连续读写。
FAT文件系统采用了一种简单而高效的分配策略,称为“FAT链式分配”。
当创建一个文件时,文件系统会为其分配一组连续的空闲簇,并将它们链接在一起形成一个簇链。
当文件大小增加时,文件系统会继续为文件分配新的簇,并更新FAT表中的链接关系。
当文件被删除时,文件系统会释放该文件占用的簇,使它们变为空闲状态。
通过这种分配策略,FAT文件系统可以高效地管理磁盘空间,但也存在碎片问题。
FAT文件系统的访问和管理主要通过文件控制块(FCB)来实现。
每个文件都有一个对应的FCB,它包含了文件的属性、大小、起始簇号等信息。
通过FCB,文件系统可以获取和修改文件的元数据,如文件名、创建时间、修改时间等。
此外,FCB还包含了文件的读写指针,用于记录当前读写位置。
了解电脑文件系统FATNTFS和exFAT的区别与使用场景
了解电脑文件系统FATNTFS和exFAT的区别与使用场景了解电脑文件系统FAT、NTFS和exFAT的区别与使用场景电脑文件系统是一种组织和管理计算机硬盘或其他存储设备上文件和目录的方法。
常见的电脑文件系统包括FAT、NTFS和exFAT。
本文将介绍这三种文件系统的区别和使用场景。
一、FAT文件系统FAT(File Allocation Table)是DOS(Disk Operating System)和早期的Windows操作系统所使用的文件系统。
它的特点是简单、容易实现和兼容性好。
FAT文件系统将硬盘或存储设备划分为多个区块(cluster),并在磁盘上维护一个表格来记录文件和目录的存储位置。
FAT文件系统的优点是兼容性好,几乎所有的操作系统都能够读写FAT格式的存储设备。
然而,它也存在一些缺点,比如文件和目录的最大容量受到限制,文件名长度有限制,无法实现高级的访问权限控制等。
使用场景:FAT文件系统适用于需求简单的场景,比如在一些老旧的嵌入式设备上(如音频播放器、数码相机等),或者在需要与多个操作系统交互的存储设备上(如USB闪存驱动器)。
二、NTFS文件系统NTFS(New Technology File System)是Windows NT系列操作系统引入的文件系统,它采用了更先进的设计和管理方法。
与FAT文件系统相比,NTFS的功能更加强大,支持更大的存储容量和更高级的功能。
NTFS文件系统的特点包括:支持文件和目录的压缩和加密、支持动态磁盘、支持访问控制列表(ACL)和权限管理、支持文件系统日志和故障恢复等。
NTFS文件系统的优点是功能丰富,具备高级的权限管理和数据安全性保护能力。
然而,NTFS文件系统在某些低资源设备上可能存在着一定的兼容性问题。
使用场景:NTFS文件系统适合用于大容量存储设备,比如桌面电脑、服务器以及其他需要高级功能和数据安全性的场景。
三、exFAT文件系统exFAT(Extended File Allocation Table)是针对大容量存储设备而设计的文件系统。
FAT文件系统原理及实现
FAT文件系统原理及实现
邓剑;杨晓非;廖俊卿
【期刊名称】《计算机与数字工程》
【年(卷),期】2005(033)009
【摘要】介绍了存储设备的分区以及FAT文件结构,并给出了在嵌入式系统中,实现FAT文件系统的方法.
【总页数】4页(P105-108)
【作者】邓剑;杨晓非;廖俊卿
【作者单位】华中科技大学电子科学与技术系,武汉,430074;华中科技大学电子科学与技术系,武汉,430074;华中科技大学电子科学与技术系,武汉,430074
【正文语种】中文
【中图分类】TP334
【相关文献】
1.基于S3C2440和μC/OS的FAT文件系统的设计与实现 [J], 费超;赵英俊
2.基于STM32的MicroSD卡Fat文件系统快速实现 [J], 史胜伟;潘冀宁;孙慧洋
3.exFAT文件系统解析及其数据恢复原理探究 [J], 刘彦;张曦
4.NIOS下实现存储速度可调的SD卡FAT文件系统 [J], 刘人萍;汪涛
5.在Ucos-Ⅱ嵌入式操作系统平台上实现exfat文件系统 [J], 杨利
因版权原因,仅展示原文概要,查看原文内容请购买。
FAT文件系统分析
FAT文件系统的数据结构中有两个重要的结构:文件分配表和目录项:文件和文件夹内容储存在簇中,如果一个文件或文件夹需要多余1个簇的空间,则用FAT表来秒速如何找到另外的簇。
FAT结构用于指出文件的下一个簇,同时也说明了簇的分配状态。
FAT12、FAT16、FAT32这三种文件系统的主要区别在于FAT项的大小不同。
FAT文件系统的每一个文件和文件夹都被分配到一个目录项,目录项中记录着文件名、大小、文件内容起始地址以及其他一些元数据。
在FAT文件系统中,文件系统的数据记录在“引导扇区DBR”中。
引导扇区位于整个文件系统的0扇区,是文件系统隐藏区域的一部分,我们称其为DBR(DOS Boot Recorder ——DOS引导记录)扇区,DBR中记录着文件系统的起始位置、大小、FAT表个数及大小等相关信息。
在FAT文件系统中,同时使用“扇区地址”和“簇地址”两种地址管理方式。
这是因为只有存储用户数据的数据区使用簇进行管理(FAT12和FAT16的根目录除外),所有簇都位于数据区。
其他文件系统管理数据区域是不以簇进行管理的,这部分区域使用扇区地址进行管理。
文件系统的起始扇区为0号扇区。
FAT32的保留区FAT32文件系统的开始部分有一个由若干扇区组成的保留区,保留区的信息会记录在DBR扇区中,比较常见的为32、34或38个扇区。
引导扇区:引导扇区是FAT32文件系统的第一个扇区,也称DBR扇区。
包含以下基本信息:·每扇区字节数·每簇扇区数·保留扇区数·FAT表个数·文件系统大小(扇区数)·每个FAT表大小(扇区数)·根目录起始簇号·其他附加信息说明:我们可以通过每个FAT表的大小扇区数乘以FAT的个数得到FAT区域的大小;通过保留扇区数和FAT区域的大小就可以得知数据区的起始位置,也即文件系统第一簇的位置。
由根目录的簇号和第一簇的位置就可以得到根目录的位置。
第2节操作系统 FAT文件系统
var cat bo hex
xx
2、从xx的第一个磁盘块中找test.c的FCB, 若找不到,从FAT中找下一个磁盘块地 址……
3、如果找到,把test.c的FCB放到内存的一个 表中,返回表的行号
data test.c mail
a
data
第5单元 文件系统
第3节 FAT文件系统 ---------串联文件的代表 最兼容的文件系统 串联文件 FAT文件系统磁盘结构 树型目录 如何通过文件路径名映射磁盘块 分配磁盘块 举例
串联文件 FAT文件系统磁盘结构 树型目录 如何通过文件路径名映射磁盘块 分配磁盘块 优化 举例
优化措施
• 提供用户接口 • 当前目录
用户接口
• Open:通过文件路径名找到该文件的FCB,复制到内存 • Read:通过文件的FCB找到数据块 • Write:可能需要分配磁盘块 • Close:将文件的FCB从内存中删除
open、close操作可以没有,但是为了减少频 繁的磁盘访问,都会这么做
优化措施
• 提供用户接口 • 当前目录
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机《操作系统课程设计》任务书模拟实现单级目录、单级索引的索引文件系统一、课程设计的性质和目的操作系统课程设计是计算机专业的专业课程,通过课程设计使学生进一步巩固课堂所学知识,全面熟悉、掌握操作系统的基本设计方法和技巧,进一步提高分析问题、解决问题及上机操作能力,为将来从事计算机工作打下一定的专业基础。
二、设计课题模拟实现单级目录的FAT文件系统基本思路:用二进制文件空间模拟磁盘空间,用文件块操作模拟磁盘块操作。
基本设计要求:1、实现如下文件系统功能(过程或函数):a、打开文件系统FILE *OPENSYS(char *filename);b、关闭文件系统int CLOSESYS(FILE *stream);c、显示目录void LISTDIR(void);d、建立文件int FCREATE(char *filename);e、删除文件int FDELETE(char *filename);f、打开文件int FOPEN(char *filename);g、关闭文件int FCLOSE(int fileid);h、文件块读int FREAD(void *ptr, int n, int fileid);i、文件块写int FWRITE(void *ptr, int n, int fileid);j、判断文件结束int FEOF(int fileid);k、获取文件指针long FGETPOS(int fileid);l、设置文件指针int FSETPOS(int fileid, long offset);m、取得文件长度long FGETLEN(char *filename);2、提供文件系统创建程序3、有功能检测模块4、为简化程序设计,假定目录区域大小固定。
文件系统空间划分:可以使用的C语言文件操纵函数:FILE *fopen(const char *filename, const char *mode);int fclose(FILE *stream);int fseek(FILE *stream, long offset, int whence);long ftell(FILE *stream);size_t fread(void *ptr, size_t size, size_t n, FILE *stream);size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);目录一、程序的功能 (3)二、程序的基本设计思路 (3)三、主要的数据结构 (4)4.1创建文件流程图 (6)4.3 FREAD函数流程图 (8)五、程序调试及其运行结果 (9)六、设计总结与心得体会 (12)七、附录(源程序清单) (13)一、程序的功能该程序主要模拟实现单级目录的FAT文件系统,该系统要求能实现对文件的创建、删除、读、写、打开、关闭以及能显示目录等操作,在创建文件时,系统首先为新文件分配所需的外存空间,并且在文件系统的相应目录中,建立一个目录项,该目录项记录了新文件的文件名及其在外存中的地址等属性。
而当已经不再需要某个文件时,便可以把它从文件系统中删除。
这时执行的是与创建新文件相反的操作。
系统先从目录中找到要删除的文件项,使之成为空项,紧接着回收该文件的存储空间,用于下次分配。
通过读指针,将位于外部存储介质上的数据读入到内存缓冲区这样就实现了文件的读取,通过写指针,将内存缓冲区中的数据写入到位于外部存储介质上的文件中。
在开始使用文件时,首先必须打开文件。
这可以将文件属性信息装入内存,以便以后快速查用。
在完成文件使用后,应该关闭文件。
这不但是为了释放内存空间,而且也因为许多系统常常限制可以同时打开的文件数。
当创建文件时,先在目录表中查找是否存在此文件表,若存在则表示文件同名不能创建,否则在目录表中为此文件先建立一个目录项,保存文件的一些基本属性,如创建日期、大小、文件名等,并保存文件的首索引块扇区号,对文件读写也是先在目录项里查找文件是否存在,再根据文件的首索引块扇区号,查找对应块号中的内容对其进行读写操作,删除一个文件后回收为其分配的空间,并更新目录表、修改文件控制块。
显示目录项可以显示文件名、长度以及创建日期。
二、程序的基本设计思路模拟实现单极目录FAT的文件系统基本思路:用二进制文件空间模拟磁盘空间,用文件块操作模拟磁盘块操作。
在一个文件系统中对文件进行操作,实现文件的创建、读写等等操作。
在创建文件时先在目录项中进行查找,若创建的文件已存在,文件的创建首先检验目录是否为空,为空则把文件夹或文件连接到该目录下,不为空则把检查目录下是否有同名文件夹或文件,有则提示创建不成功,而文件夹打开是则把文件夹名称及其地址压入打开文件夹栈,文件关闭则把文件夹名称及其地址从打开文件夹栈中抛出。
文件夹和文件的删除,文件夹下没有打开的文件或文件没有打开才能删除,否则删除失败,每次操作成功都要更改目录和FCB信息。
该过程都保存在文件中,是对文件的操作。
本系统建于Windows平台,开发环境为WIN-TC。
三、主要的数据结构单级目录单级索引文件系统:常量#define BlockSize 512#define DirSize 32保留扇区结构struct ReserveBlock{int sysblocknum; /*文件系统总扇区数*/int resblocknum; /*保留扇区扇区数*/int mapblocknum; /*字节映像图扇区数*/int rootblocknum; /*根目录区扇区数*/char fillchar[BlockSize-4*sizeof(int)]; /*填充字节*/};目录结构struct DirBlock{char filename[11]; /*文件名限长11个字符*/char fillchar[DirSize-4*sizeof(int)-sizeof(long int)-11]; /*填充字节*/ long filelen; /*文件长度*/int year,month,day; /*定义年月日*/int firstindexaddr; /*文件首索引块扇区号*/};索引块结构struct IndexBlock{int dataaddr[BlockSize/sizeof(int)-1]; /*数据块块号数组*/int nextindexaddr; /*本文件下一索引块块号*/};索引节点结构struct IndexNode{struct IndexBlock block; /*索引块数据*/int blockaddr; /*本节点索引块块号*/struct IndexNode *nextnode; /*指向下一索引节点的指针*/};FCB(文件控制块)结构struct FCBBlock{int fileid; /*文件标识*/struct DirBlock fileinfo; /*目录信息*/long filepos; /*文件读写指针*/int fdtblockaddr; /*目录项所在块号*/int fdtblockindex; /*目录项所在块内序号*/struct FCBBlock *next; /*指向下一个文件控制块的指针*/struct IndexNode *firstindexnode; /*指向第一个索引节点的指针* /}四、相关流程图4.1创建文件流程图4.2删除文件流程图4.3 FREAD函数流程图五、程序调试及其运行结果图1图1为欢迎界面在输入系统块的数目后产生的界面,必须先要输入start开始运行文件系统才能完成建立文件(creat),显示文件目录(list),打开文件(open),关闭文件(close),删除文件(delete),写文件块(write),读文件块(read)等等操作图2输入start成功打开文件系统,再输入creat来创建文件,此图为创建成功后的界面图3图3表示输入list显示文件目录,如图所示创建了aaa,bbb,ccc三个文件图4图4显示的是成功打开和成功关闭文件图5输入read读取文件,可以设置读文件的初始位置以及读取文件的长度.图6 输入write写文件图7如图所示删除aaa,bbb,ccc三个文件六、设计总结与心得体会通过一个学期的学习,操作系统的课程设计也要结课了,总的来说经过这门课的学习收获还是挺大的,它不但使我更了解了课本知识,巩固了课本知识,而且也使我的编程能力有了一定的提高。
这次课程设计是对操作系统的一个总结和复习的过程,课设的过程是个自我探索、自我学习的过程,其中,我们不仅学到了专业的知识,也提升了自己的学习能力。
在此次课程设计中也遇到了不少的问题和困难,但是通过自己的努力和向同学讨教都把他一一的给解决了,总之,通过这次课程设计,是我对文件系统有了更深一部的了解,让我对文件系统不再陌生,当然自己还有很多不足的地方,希望自己在以后的学习过程中不断的改进,这样才能让自己进步,才能让自己更上一层楼。
七、附录(源程序清单)#include <stdio.h>#include <string.h>#include <stdlib.h>#define BlockSize 512#define DirSize 32#define RootSize 2struct ReserveBlock{int sysblocknum;/*文件系统总扇区数*/int resblocknum;/*保留扇区扇区数*/int fatblocknum;/*FAT表扇区数*/int rootblocknum;/*根目录区扇区数*/char fillchar[BlockSize-4*sizeof(int)];/*填充字节*/};struct DirBlock{char filename[11]; /*文件名限长11个字符*/char fillchar[DirSize-4*sizeof(int)-sizeof(long int)-11];/*填充字节*/long filelen; /*文件长度*/int year,month,day; /*日期*/int firstblockaddr; /*文件首块扇区号*/};struct FCBBlock{int fileid; /*文件标识*/long filepos; /*文件读写指针*/int fdtblockindex; /*目录项所在块内序号*/struct FCBBlock *next;/*指向下一个文件控制块的指针*/ };struct ReserveBlock sys1; /*保留块*/struct FCBBlock *fcb; /*fcb头指针*/ struct DirBlock fil[32],*dir; /*目录*/int *fat1; /*fat表头指针*/char *str,*ptr; /*读、写缓冲区首地址*/char fillchar[BlockSize]; /*填充字符*/FILE *fp; /*文件指针*/FILE *OPENSYS(char *filename) /*打开文件系统*/{ int i;fp=fopen(filename,"rb+");fread(&sys1,1,BlockSize,fp); /*读保留扇区*/fat1=(int *)malloc(sys1.fatblocknum*BlockSize);for(i=0;i<sys1.fatblocknum;i++) /*读fat表*/ fread(fat1+i*BlockSize,BlockSize,1,fp);fseek(fp,(sys1.fatblocknum+sys1.resblocknum)*BlockSize,0);dir=fil;for(i=0;i<sys1.rootblocknum;i++) /*读目录*/fread(dir+i*BlockSize/DirSize,BlockSize,1,fp);return fp;}int CLOSESYS(FILE *stream) /*关闭文件系统*/{ int i;fseek(stream,sys1.resblocknum*BlockSize,0);for(i=0;i<sys1.fatblocknum;i++) /*回写fat表*/ fwrite(fat1+i*BlockSize,BlockSize,1,stream);fseek(fp,(sys1.fatblocknum+sys1.resblocknum)*BlockSize,0);for(i=0;i<sys1.fatblocknum;i++) /*回写目录*/fwrite(dir+i*BlockSize/DirSize,BlockSize,1,fp);fclose(fp);return 0;}void LISTDIR(void) /*显示目录*/ { int i,flag=0;for(i=0;i<32;i++){ if(fil[i].firstblockaddr!=0){ if(flag==0)printf("文件名大小创建日期\n");flag=1;printf("%s%8ld%4d%4d%4d\n",fil[i].filename,fil[i].filelen,fil[i].year,fil[i].month,fil[i].day);} }}int FCREATE(char *filename) /*创建文件*/{int i,flag=0,j,k=0,flag1=0,flag2=0,a;int n,m;a=strlen(filename);if(a>10)return 1;for(i=0;i<sys1.rootblocknum*BlockSize/DirSize;i++) /*查找是否重名*/if(strcmp(filename,fil[i].filename)==0){printf("文件名已存在!\n");return 3;}for(i=(sys1.fatblocknum+sys1.resblocknum+sys1.rootblocknum);i<sys1.sysblocknum;i++) if(fat1[i]==0) /*查看是否有空的块*/flag++;if(flag==0){ printf("磁盘已满");/*统计结果为0,则磁盘已满*/return 0;}printf("空闲块数:%d\n",flag);printf("请输入文件长度:");for(j=0;j<32;j++)if(fil[j].firstblockaddr==0)break;while(1){scanf("%d",&dir[j].filelen);/*输入目录项中文件的长度*/n=(dir[j].filelen/BlockSize)+(dir[j].filelen%BlockSize?1:0);if(n<0||n>flag)/*文件长度小于0或大于空闲的空间*/{printf("文件太长!\n");printf("请重新输入:");}elsebreak;}for(i=(sys1.fatblocknum+sys1.resblocknum+sys1.rootblocknum);i<sys1.sysblocknum;i++) /*分配一块空间*/if(fat1[i]==0){ fat1[i]=-1;break;}dir[j].firstblockaddr=i+1;strcpy(dir[j].filename,filename); /*输入文件相关的信息*/dir[j].filename[a]='\0';printf("输入年份:");scanf("%d",&dir[j].year);printf("输入月份:");scanf("%d",&dir[j].month);printf("输入日期:");scanf("%d",&dir[j].day);return (0);}int FDELETE(char *filename) /*删除文件*/{int i,j,k,n,flag=1;struct FCBBlock *p;p=fcb;while(p) /*查看是否关闭了文件*/{ if(strcmp(filename,fil[p->fdtblockindex].filename)==0)return 1;elsep=p->next;}for(i=0;i<sys1.rootblocknum*BlockSize/DirSize;i++) /*查找是否存在要删除的文件*/if(strcmp(filename,fil[i].filename)==0){ flag=1;break;}if(flag==0)return 2;j=fil[i].firstblockaddr;while(1){k=fat1[j-1]; /*将要删除的文件的块用0填充*/fseek(fp,(j-1)*BlockSize,0);fwrite(&fillchar,1,BlockSize,fp);fat1[j-1]=0;if(k==-1)break;elsej=k;}memset(&fil[i],0,DirSize); /*将要删除的文件的目录用0填充*/return 0;}int FOPEN(char *filename) /*打开文件*/{int i,j=0,k,flag=0,id;struct FCBBlock *p,*q,*r;p=fcb;for(i=0;i<sys1.rootblocknum*BlockSize/DirSize;i++) /*查找要打开的文件是否存在*/if(strcmp(filename,fil[i].filename)==0){ flag=1;break;}if(flag==0)return 0;if(fcb==NULL){ fcb=(struct FCBBlock *)malloc(sizeof(struct FCBBlock));fcb->fileid=j+1;fcb->filepos=0;fcb->next=NULL;fcb->fdtblockindex=i;id=j+1;return id;}else{ while(fcb){j++;if(strcmp(filename,fil[fcb->fdtblockindex].filename)==0) /*判断是否已经打开*/return 0;q=fcb;fcb=fcb->next;}r=(struct FCBBlock *)malloc(sizeof(struct FCBBlock)); /*创建fcb*/r->fileid=j+1;r->filepos=0;r->next=NULL;r->fdtblockindex=i;q->next=r;}id=j+1;fcb=p;return id; /*返回打开的文件的标识fileid*/ }long FGETLEN(char *filename) /*获取文件的长度*/{ int i;for(i=0;i<sys1.rootblocknum*BlockSize/DirSize;i++)if(strcmp(filename,fil[i].filename)==0)return fil[i].filelen;return -1;}int FCLOSE(char *filename)/*关闭文件*/{ int flag=0;struct FCBBlock *f,*p;f=fcb;if(strcmp(filename,fil[fcb->fdtblockindex].filename)==0){ flag=1;fcb=fcb->next;p=fcb;while(p){p->fileid-=1;p=p->next;}return flag;}p=f;f=f->next;while(f){if(strcmp(filename,fil[f->fdtblockindex].filename)==0){ flag=1;p=f->next;/*p=p->next;*/while(p){ p=p->next;p->fileid-=1;}free(f);return flag;}p=f;f=f->next;}if(flag==0){ printf("The file has not open!\n'");return flag;}return 0;}int FREAD(char *str, int n, int fileid) /*读文件*/{ int m,i,j=0,k,l,len,n1,n2=0;struct FCBBlock *p;p=fcb;while(p) /*查找要读的文件的fcb*/{if(p->fileid==fileid)break;elsep=p->next;}if(p==NULL)return 1;len=fil[p->fdtblockindex].filelen;l=p->filepos;if((l+n)>len)return 2;j=(l/BlockSize)+(l%BlockSize?1:0); /*求文件指针所在文件的相对块号*/m=((l+n)/BlockSize)+((l+n)%BlockSize?1:0);k=fil[p->fdtblockindex].firstblockaddr;for(i=1;i<j;i++) /*求文件指针所在的块号*/k=fat1[k-1];str=(char *)malloc((m-j+1)*BlockSize+1); /*分配读取的缓冲区*/for(i=0;i<(m-j+1);i++) /*读文件*/{fseek(fp,(k-1)*BlockSize,0);fread(&str[i*BlockSize],BlockSize,1,fp);k=fat1[k-1];}str[n+l-(j-1)*BlockSize]='\0'; /*截断多读的内容*/if(l!=0)str=&str[l-(j-1)*BlockSize];p->filepos=n+l; /*修改文件指针*/printf("%s\n",str);return 0;}int FWRITE(char *ptr, int n, int fileid) /*文件写*/{long l;int m,i=0,j,k=0,num,flag=0,flag1=0,b,flag2=0;int n1,n2=0,n3,c;struct FCBBlock *p;char *st1,*st2;st1=(char *)malloc(BlockSize);p=fcb;while(p) /*查找文件的fcb*/{if(p->fileid==fileid)break;elsep=p->next;}if(p==NULL)return 1;l=p->filepos;n1=fil[p->fdtblockindex].firstblockaddr;while(n1!=-1){n2++;m=n1-1;n1=fat1[n1-1];}if((l+n)>n2*BlockSize) /*判断是否要追加空间*/{ n3=(l+n)/BlockSize+((l+n)%BlockSize?1:0)-n2; /*追加空间*/for(i=(sys1.fatblocknum+sys1.resblocknum+sys1.rootblocknum);i<sys1.sysblocknum;i++) if(fat1[i]==0)flag++;if(flag==0){ printf("磁盘已满");return 2;}if((l+n-fil[p->fdtblockindex].filelen)>flag*BlockSize)return 3;for(i=(sys1.fatblocknum+sys1.resblocknum+sys1.rootblocknum);i<sys1.sysblocknum;i++) {if(fat1[i]==0){k++;if(k>=n3){fat1[m]=i+1;fat1[i]=-1;break;}elsefat1[m]=i+1;m=i;} }}flag=0;k=0;n3=(l+n)/BlockSize+((l+n)%BlockSize?1:0);j=(l/BlockSize)+(l%BlockSize?1:0); /*求文件指针所在文件的相对块号*/st2=(char *)malloc((n3-j+1)*BlockSize);if(l==0)j=1;num=fil[p->fdtblockindex].firstblockaddr;for(i=1;i<j;i++)num=fat1[num-1];if(!l%BlockSize) /*写第1块*/{fseek(fp,(num-1)*BlockSize+l-(i-1)*BlockSize,0);fread(st2,BlockSize,1,fp);for(c=0;c<n;c++)st2[c]=ptr[c];fseek(fp,(num-1)*BlockSize+l-(i-1)*BlockSize,0);fwrite(st2,BlockSize,1,fp);num=fat1[num-1];fflush(fp);}else{ fseek(fp,(num-1)*BlockSize,0);fread(st2,BlockSize,1,fp);for(c=0;c<n;c++)st2[c+l-(j-1)*BlockSize]=ptr[c];fseek(fp,(num-1)*BlockSize,0);fwrite(st2,BlockSize,1,fp);num=fat1[num-1];fflush(fp);}for(i=1;i<(n3-j);i++) /*写第2块-倒数第2块*/ { fseek(fp,(num-1)*BlockSize,0);fwrite(st2+i*BlockSize,BlockSize,1,fp);num=fat1[num-1];fflush(fp);}if((n3-j)>0) /*写最后一块*/{fseek(fp,(num-1)*BlockSize,0);fread(st2+i*BlockSize,BlockSize,1,fp);for(c=0;c<(n-((j*BlockSize-l)+(i-1)*BlockSize));c++)st2[c+i*BlockSize]=ptr[c+(j*BlockSize-l)+(i-1)*BlockSize];fseek(fp,(num-1)*BlockSize,0);fwrite(st2+i*BlockSize,BlockSize,1,fp);fflush(fp);}p->filepos=l+n; /*修改文件指针*/if((n+l)>fil[p->fdtblockindex].filelen)fil[p->fdtblockindex].filelen=n+l; /*修改文件长度*/return 0;}int FEOF(int fileid) /*判断文件是否结束*/{int flag;struct FCBBlock *p;p=fcb;while(p){if(p->fileid==fileid)if(p->filepos>=fil[p->fdtblockindex].filelen)return 0;elsereturn 1;}return 2;}long FGETPOS(int fileid){struct FCBBlock *p;p=fcb;while(p){if(p->fileid==fileid)return (p->filepos);elsep=p->next;}printf("get faile!\n");return(-1);}int FSETPOS(int fileid, long offset) /*设置文件指针*/ {struct FCBBlock *p;p=fcb;while(p){if(p->fileid==fileid){if(offset>fil[p->fdtblockindex].filelen||offset<0)return 1;else{p->filepos=offset;return 0;}}p=p->next;}printf("get faile!\n");return(2);}void DISPLAY(){printf("\t\t---------------欢迎使用FAT文件系统---------------\n");printf("\t\t------------------制作人:王兴宙------------------\n\n");printf("\t\t-------------------------------------------------\n");printf("\t\t\t\t 请输入您要选择的功能:\n\n");printf("\t\t\t\t 开始运行文件系统:start\n");printf("\t\t\t\t 建立文件:creat\n");printf("\t\t\t\t 显示文件目录:list\n");printf("\t\t\t\t 删除文件:del\n");printf("\t\t\t\t 打开文件:open\n");printf("\t\t\t\t 关闭文件:close\n");printf("\t\t\t\t 文件块读:read\n");printf("\t\t\t\t 文件块写:write\n");printf("\t\t\t\t 设置文件指针:set\n");printf("\t\t\t\t 获取文件指针:getp\n");printf("\t\t\t\t 获取文件长度:getl\n");printf("\t\t\t\t 退出文件系统:exit\n");printf("\t\t---------------------------------------------------\n");}void test(char *filename) /*测试函数*/{char *t,cmd[10],fname[12];struct FCBBlock *p;int flag,len,id,flag1=0,l;while(1){DISPLAY();scanf("%s",cmd);if(!strcmp(cmd,"start")) /*开始运行系统命令*/ {fp=OPENSYS(filename);printf("成功打开文件系统\n");while(1){scanf("%s",cmd);if(!strcmp(cmd,"creat")) /*创建文件*/ {printf("请输入文件名:");scanf("%s",fname);flag=FCREATE(fname);if(flag==0)printf("文件创建成功!\n");if(flag==1)printf("文件名太长!\n");if(flag==2)printf(" 磁盘已满!\n");if(flag==3)printf("文件已经存在!\n");}else if(!strcmp(cmd,"list")) /*显示文件目录*/ LISTDIR();else if(!strcmp(cmd,"del")) /*删除文件*/ {scanf("%s",fname);flag=FDELETE(fname);if(flag==0)printf("成功删除文件!\n");if(flag==1)printf("文件被打开,要删除文件请先关闭文件!\n"); }else if(!strcmp(cmd,"open")) /*打开文件*/ {scanf("%s",fname);flag=FOPEN(fname);if(flag==0)printf("文件没有被发现,不能打开!\n");elseprintf("成功打开,文件ID是:%d\n",flag);}else if(!strcmp(cmd,"close")) /*关闭文件*/ {scanf("%s",fname);flag=FCLOSE(fname);if(flag==1)printf("成功关闭文件!\n");}else if(!strcmp(cmd,"read")) /*读文件*/ {scanf("%d",&id);p=fcb;printf("请输入读文件大小:");scanf("%d",&len);flag=FREAD(str,len,id);if(flag==1)printf("文件没有被打开,请先打开文件!\n");if(flag==2)printf("读取文件失败\n");}else if(!strcmp(cmd,"write")) /*写文件*/ { scanf("%d",&id);printf("请输入写文件大小:");scanf("%d",&len);ptr=(char *)malloc(len+1);printf("请输入内容:");scanf("%s",ptr);flag=FWRITE(ptr,len,id);if(flag==1)printf("文件没有被打开,请先打开文件!\n");if(flag==1)printf("wu kong jian!\n");if(flag==3)printf("写操作失败!\n");if(flag==0)printf("成功写文件!\n");}elseif(!strcmp(cmd,"set")) /*设置文件指针*/{scanf("%d",&id);printf("输入指针:");scanf("%d",&l);flag=FSETPOS(id,l);if(flag==0)printf("成功设置指针!\n");if(flag==1)printf("指针太长或错误!\n");if(flag==2)printf("这个文件没有打开!\n");}else if(!strcmp(cmd,"getp")) /*获取文件指针*/ {scanf("%d",&id);flag=FGETPOS(id);if(flag!=-1)printf("pos is:%d\n",flag);if(flag==-1)printf("这个文件不能打开!\n");}elseif(!strcmp(cmd,"getl")) /*获取文件长度*/{scanf("%s",fname);flag=FGETLEN(fname);if(flag==-1)printf("这个文件不能被发现!\n");elseprintf("文件长度:%d\n",flag);}else if(!strcmp(cmd,"exit")) /*关闭文件系统*/ {flag=CLOSESYS(fp);if(flag==0)printf("成功关闭文件管理系统!\n");break;}elseprintf("这条命令错误!\n");}}elseprintf("这条命令错误!\n");}}int main(){ struct ReserveBlock sys;char filename[]="fatsys.dat";int *fat;int i,j;system("graftabl 936");clrscr();fcb=NULL;memset(&sys,255,BlockSize); /*磁盘格式化*/printf("请输入文件系统块的数目(5~32767):");scanf("%d",&(sys.sysblocknum));sys.resblocknum=1;sys.fatblocknum=sys.sysblocknum/(BlockSize/sizeof(int))+((sys.sysblocknum%(BlockSize/sizeof(int)))?1:0);fat=(int*)malloc(BlockSize*sys.fatblocknum);memset(fat,255,BlockSize*sys.fatblocknum);memset(fat,0,sizeof(int)*sys.sysblocknum);sys.rootblocknum=RootSize;j=sys.resblocknum+sys.fatblocknum+sys.rootblocknum;for (i=0;i<j;i++)fat[i]=-1;memset(&fillchar,0,BlockSize);fp=fopen(filename,"w+b");fwrite(&sys,1,BlockSize,fp);for (i=0;i<sys.fatblocknum;i++)fwrite(fat+i*BlockSize/sizeof(int),1,BlockSize,fp);j=sys.resblocknum+sys.fatblocknum;for(i=0;i<(sys.sysblocknum-j);i++)fwrite(&fillchar,1,BlockSize,fp);fclose(fp);free(fat);test(filename);return 0;}模拟实现单级目录、单级索引的索引文件系统一、课程设计的性质和目的操作系统课程设计是计算机专业的专业课程,通过课程设计使学生进一步巩固课堂所学知识,全面熟悉、掌握操作系统的基本设计方法和技巧,进一步提高分析问题、解决问题及上机操作能力,为将来从事计算机工作打下一定的专业基础。