设计文件系统|用c++设计一个简单的二级文件系统

设计文件系统|用c++设计一个简单的二级文件系统的第1张示图

㈠ 文件系统设计中的 Sectorsize有什么用

操作系统的文件系统是操作系统用于明确磁盘或分区上的文件的方法和数据结构;即在磁盘上组织文件的方法。文件系统的格式大致有如下:FATPC机使用的文件系统是FAT16。像基于MS-DOS,Win95等系统都采用了FAT16文件系统。后来在Win98开始推出了增强的文件系统FAT32。同FAT16相比,FAT32主要具有以下特点:同FAT16相比FAT32最大的优点是可以支持的磁盘大小达到32GB,但是不能支持小于512MB的分区。基于FAT32的Win2000可以支持分区最大为32GB;而基于FAT16的Win2000支持的分区最大为4GB。NTFSNTFS文件系统是一个基于安全性的文件系统,是WindowsNT所采用的独特的文件系统结构,它是建立在保护文件和目录数据基础上,同时照顾节省存储资源、减少磁盘占用量的一种先进的文件系统。exFAT全称,扩展FAT,即扩展文件分配表是Microsoft在WindowsEmbeded5.0以上(包括WindowsCE5.0、6.0、WindowsMobile5、6、6.1)中引入的一种适合于闪存的文件系统,为了解决FAT32等不支持4G及其更大的文件而推出。对于闪存,NTFS文件系统不适合使用,exFAT更为适用。Ext2Ext2是GNU/linux系统中标准的文件系统,其特点为存取文件的性能极好,对于中小型的文件更显示出优势,这主要得利于其簇快取层的优良设计。其单一文件大小与文件系统本身的容量上限与文件系统本身的簇大小有关,在一般常见的x86电脑系统中,簇最大为4KB,则单一文件大小上限为2048GB,而文件系统的容量上限为16384GB。Ext3Ext3是一种日志式文件系统,是对ext2系统的扩展,它兼容ext2。日志式文件系统的优越性在于:由于文件系统都有快取层参与运作,如不使用时必须将文件系统卸下,以便将快取层的资料写回磁盘中。因此每当系统要关机时,必须将其所有的文件系统全部shutdown后才能进行关机。Ext4Linuxkernel自2.6.28开始正式支持新的文件系统Ext4。Ext4是Ext3的改进版,修改了Ext3中部分重要的数据结构,而不仅仅像Ext3对Ext2那样,只是增加了一个日志功能而已。Ext4可以提供更佳的性能和可靠性,还有更为丰富的功能与Ext3兼容。BtrfsBtrfs(通常念成ButterFS),是由Oracle于2007年宣布并进行中的-on-write文件系统。目标是取代Linux目前的ext3文件系统,改善ext3的限制,特别是单个文件的大小,总文件系统大小或文件检查和加入目前ext3未支持的功能,像是writablesnapshots、snapshotsofsnapshots、内建磁盘阵列(RAID)支持,以及subvolumes。Btrfs也宣称专注在“容错、修复及易于管理”。ZFSZFS源自于SunMicrosystems为Solaris操作系统开发的文件系统。ZFS是一个具有高存储容量、文件系统与卷管理概念整合、崭新的磁盘逻辑结构的轻量级文件系统,同时也是一个便捷的存储池管理系统。ZFS是一个使用CDDL协议条款授权的开源项目。HFSHFS文件系统概念分层文件系统(HierarchicalFileSystem,HFS)是一种由苹果电脑开发,并使用在MacOS上的文件系统。ReiserFSReiserFS,是一种文件系统格式,作者是HansReiser及其团队Namesys,1997年7月23日他将ReiserFS文件系统在互联网上公布。Linux内核从2.4.1版本开始支持ReiserFS。JFSJFS(JOURNALFILESYSTEM),一种字节级日志文件系统,借鉴了数据库保护系统的技术,以日志的形式记录文件的变化。JFS通过记录文件结构而不是数据本身的变化来保证数据的完整性。这种方式可以确保在任何时刻都能维护数据的可访问性。(VMFS)是一种高性能的群集文件系统,它使虚拟化技术的应用超出了单个系统的限制。VMFS的设计、构建和优化针对虚拟服务器环境,可让多个虚拟机共同访问一个整合的群集式存储池,从而显著提高了资源利用率。VMFS是跨越多个服务器实现虚拟化的基础,它可启用VMwareVmotionTM、DistributedResourceScheler和VMwareHighAvailability等各种服务。VMFS还能显著减少管理开销,它提供了一种高效的虚拟化管理层,特别适合大型企业数据中心。采用VMFS可实现资源共享,使管理员轻松地从更高效率和存储利用率中直接获益。XFSXFS是SiliconGraphics,Inc.于90年代初开发的文件系统。它至今仍作为SGI基于IRIX的产品(从工作站到超级计算机)的底层文件系统来使用。现在,XFS也可以用于Linux。XFS的Linux版的到来是激动人心的,首先因为它为Linux社区提供了一种健壮的、优秀的以及功能丰富的文件系统,并且这种文件系统所具有的可伸缩性能够满足最苛刻的存储需求。UFSUFS文件系统:基于BSD高速文件系统的传统UNIX文件系统,是Solaris的默认文件系统。默认启用UFS日志记录功能。在早期的Solaris版本中,UFS日志记录功能只能手动启用。Solaris10在运行64位Solaris内核的系统上支持多TBUFS文件系统。以前,UFS文件系统在64位系统和32位系统上的大小仅限于约1TB(Tbyte)。现在,所有UFS文件系统命令和公用程序已更新为支持多TBUFS文件系统。VXFSVeritasFileSystem(VxFS)是首个商业日志记录文件系统。通过日志记录功能,元数据更改首先写入到日志,然后再写入到磁盘。由于无需在多处写入更改,且元数据是异步写入的,因此吞吐量的速度较快。VxFS也是基于扩展区的意向日志记录文件系统。VxFS设计用于要求高性能和高可用性,并且可以处理大量数据的操作环境。上述资料整理于网络。

㈡ 用c++设计一个简单的二级文件系统

这些你都可以到相关的C++讨人论坛上找到

㈢ 如果让你设计一个文件系统那么该文件系统可以解决哪些问题

文件系统主要是管理文件用的,可以仿照windows设计,然后添加一些特色功能,主要解决的问题就一个:更方便的管理文件。

㈣ 如何设计一个分布式文件系统,给出文件和目录的更新算法

分布式文件系统设计主要关注几个方面: 设计特点、分布式能力、性能、容灾、维护和扩展、成本 分布式文件系统主要关键技术: 全局名字空间、缓存一致性、安全性、可用性、可扩展性

㈤ 基于多级文件目录的文件管理系统设计的设计原理是什么有着什么样的背景知识

Flash 存储器( Flash Memory) 是一种高可靠性、高密度的固态存储器件。 其存储方式是完全非易失性的,掉电后可以保存数据;可以在线写入,并可按页连续字节写入,存取速度快,所以嵌入式系统通常使用Flash 存储器作为存储设备。 但Flash存储器也存在着两个主要缺陷:一是在重写之前必须进行擦除,因为Flash 存储器划分成很多擦除块(SectorOErase) ,对任何一位数据进行修改必须先擦除整个块(Sector) ;二是擦除块的擦除次数有限,当一个块提前达到擦除次数上限时, 将导致整个Flash 存储器无法使用。 所以,目前PC 机上很多成熟的基于磁盘的文件系统在Flash 存储器上使用都存在着不足。嵌入式系统应具有的特点: 一是高可靠性,在恶劣环境下系统仍能正常工作;二是低消耗,受成本限制系统设计必须量体裁衣,去除冗余;三是高效率,在占用较少资源情况下保证功能需求,这样就要求算法简单,效率高。 而日志文件系统(Log-St ruct ured File System) 在数据更新时无需将数据写入原存储区域,适应Flash 存储器无法进行重写这一特点。 目前,针对Flash 存储器的缺陷而设计的Linux 下的J FFS 文件系统,就是采用简化的日志文件系统。 J FFS 文件系统将磨损均衡集成于清除机制之中,在带来掉电可恢复功能的同时,大大减少了块擦除的次数,提高了文件系统的存取速度和效率。 但是,J FFS 文件系统无法单独使用,或者使用于其它实时操作系统中。 对由于受成本和实时性限制而无法使用Linux 的一些嵌入式系统,也就无法使用J FFS 文件系统。基于上述分析,该嵌入式文件系统适合在开源实时操作系统(如μC/OS-II) 和无操作系统的情况下使用。嵌入式文件系统原理在日志文件系统中,一个文件被修改后不是被写入到原来的存储空间,而是被加到所有内容的后面,象日志一样被更新,这就是日志文件系统的基本原理。 由于同一个文件在文件系统中会留下不同的版本,所以系统需要设置一张表标注文件的最新与以前的版本。 在内容不断添加时为不将存储空间占满,系统设计了一种回收机制,回收无效内容占用的空间。日志文件系统在文件更新时不用将文件写回原来的地址,这对Flash 存储器这种存储介质最为适合。 文中所设计的嵌入式文件系统采用了日志文件系统的设计原理,以及J FFS 文件系统将磨损均衡集成于清除机制之中的方法。 该系统将一个可擦写块平分为多个簇,文件的读写以簇为单位进行。簇的状态有3 种:脏、干净和空。 脏表示所存内容已被置为无效;干净表示所存数据有效;空表示可以写入数据。 文件和目录在该系统中被作为节点,一个节点占用若干个簇,节点中的内容连续存储,但不能越过块边界存储。 该系统设置一个索引节点,保存整个系统的信息,其中包含保存有各簇状态的簇状态表。每一次文件更新后内容都将被添加至末尾处,索引节点也被更新,总是占用最末尾的干净簇。 回收脏簇时,将所要擦除块中的干净簇重写到空簇中,再进行块擦除。 当内容写至存储体末端,则从头部重新开始循环存储。 所设计的文件系统的操作过程见图1。ic72新闻中心嵌入式文件系统设计Flash 存储器中的存储结构Flash 存储器中的存储结构见图2。 该存储器中每个簇的第一个字作为簇的状态字,表示此簇是否为一个节点的首簇或空簇。 每个节点的首部存放此节点属性(文件/目录/索引节点) 和节点标识号。ic72新闻中心索引节点索引节点存放该文件系统的大部分信息。 包括32 位的索引节点更新号、一张簇状态表、下一个要被擦除块的块号、给下一个新建节点(文件或目录) 的节点编号、系统根目录信息表。系统每一次更新都会产生新的索引节点,索引节点更新号加1。 按照Flash 存储器的使用寿命10 年计算,需要每秒更新136 次以上,才能达到索引节点更新号的上限,所以认为拥有最大更新号的索引节点为最新的索引节点。 簇状态表中对应每一个簇有两个Bit 位,表示各个簇的状态(干净01 ,脏11 ,空00) 。 根目录信息表存放根目录下的各个目录项,每个目录项包括:属性(文件0x1/目录0x0) 、文件名或目录名、节点编号、此文件(或目录) 对应节点的起始簇地址、根目录表的大小可变。目录节点目录节点存放的内容有目录名,目录项个数,及所有目录项信息。 文件节点存放文件名,文件大小,文件属性及文件内容,内存中的目录结构见图3。ic72新闻中心内存数据结构及基本操作该文件系统载入(Mount ) 后,会在内存中建立一个系统的映象。 该映象包括:索引节点中的信息、目录及文件信息、每个可擦写块中包含的节点信息、未存盘的节点信息。 簇状态表、索引节点更新号、新节点编号、下一擦除块号等索引节点中的内容,在内存中均作为不同的变量。 内存中为每个文件和目录都建立了映象,数据结构见图4 和图5。ic72新闻中心ic72新闻中心内存中的文件节点不包含文件真正的数据,而使用指针。 文件被打开时,在内存中创建一块新存储区域存放数据,数据指针便指向此存储区,未被打开时,此指针指向空。 对于每个目录有1 个目录层数,表示此目录的深度,如根目录的目录层数为0 ,根目录的下一级目录则为1 ,依此类推。 存储地址保存文件或目录在Flash 中的地址。 文件和目录都被存在上一级目录下,所属目录指针即指向上一级目录在内存中的数据结构,根目录的所属目录指针即为空。 对于同目录下的不同节点,在内存中使用链表将其串联,同目录文件指针即联成链表。 链表的首指针保存在上一级目录中,首目录项指针即指向链表的首项。 为提高块擦写的效率,存储在同一个可擦写块中的各个节点在内存中也建立一个链表,块队列指针即用于连成此链表。 为标识被修改的节点,利用一个未保存队列,未保存队列指针即用来建立此队列。该文件系统载入(mount ) 时,首先顺序扫描Flash 中的每个索引节点,查找出最大的索引节点更新号,此更新号对应的索引节点即为最新的索引节点。 查找到最新索引节点后,将簇状态表等信息映射到内存的数据结构中。 依据索引节点中的根目录信息,遍历所有节点,建立内存中的目录文件结构,并将节点添加到对应的擦写块队列中。 对一个文件编辑并保存的过程见图6。ic72新闻中心文件打开时,先在内存中分配一块空间作为数据区,将内容写入,并定位文件节点的数据指针指向该内存中的数据区。 如果文件内容被修改,就将文件节点添加到未存盘队列,依次写入Flash 存储器中,并修改簇状态表。 保存时将内存中数据区内容写入F 中,释放申请的内存空间,修改节点中的数据指针和簇状态表,再将文件的所有上级目录重新写入Flash ,最后将更新后的索引节点内容写入Flash。 如果文件未被修改,则只需修改数据指针即可。节点加入未存盘队列的顺序按照目录层数的大小排列,文件节点排在队列首,目录层数最大的排在其后,目录层数为1 的排在队列末尾,根目录不加入未存盘队列。嵌入式文件系统特殊处理机制均衡擦写机制为了避免任意一个可擦除块因擦写次数过多而过早报废,文件系统对Flash擦写时采用了均衡擦写机制。 考虑到系统的精简性,擦写在整片Flash 的各块中依次进行,一块擦写完后,下一个被擦写的块即为后一个块,在系统的索引节点中保存了下一个要擦除的块号。 当文件系统中的剩余空间减少到设定值时,系统会擦除此块,以回收脏簇占用的空间。 对应每个可擦写块都有一个节点队列,此块中包含的节点都加入其中。块擦除的流程见图7。ic72新闻中心首先,将未保存于队列中的节点保存,清未保存队列。 然后将块队列中的所有文件节点转移到空簇中,同时将文件路径上的各级目录加入到未存盘队列中。 对于块队列中的目录节点,则将它和其路径上的各级目录加入未存盘队列中,按照未保存队列的顺序,依次将各个目录写入Flash 中,最后写入最新的索引节点。 因为目录节点加入未存盘队列时,按照目录层数的大小排列,所以按照未保存队列的顺序写入时,可以保证当一个目录要被写入Flash 时,它的所有下级目录已被写入Flash 中。 所有下级目录在Flash 中的存储地址都已确定。当该文件系统的空间将达到存储上限时,可能会出现特殊情况,即废簇回收时,空簇的空间不足,无法将所有干净簇重写。 文件系统为此建立了应急机制,先将文件节点内容存在内存中,这时新建一个临时未保存队列,专门保存文件节点,在块擦写完成后,将剩余的文件节点写入新的空簇中,其算法与图7 所示流程大致相同。 但是,一旦在擦写时断电,会导致该块上的所有数据丢失。断电错误处理机制当系统遭遇断电重新启动后,索引节点中的信息会与系统中的状态不符,这时便需要错误处理机制。 错误一般是索引节点中标注的空簇已被写入了数据,错误处理就是将此簇标志为脏簇,并查找下一个空簇重新写入。多任务处理机制该文件系统允许同时打开多个文件,在多任务操作系统下,为了避免冲突建立了多任务处理机制。 系统允许打开的多个文件在内存中同时被编辑修改,但是对Flash 写入操作有限制。 处理方法是设立Flash 写入保护区,在此区中只允许当前正在执行的任务执行Flash 写入操作。 实现Flash 写入保护区的方法是建立一个初始值为1 的信号量,当一个节点需要Flash 写入时,首先申请信号量,完成后再释放信号量。 Flash 写入保护区见图6 、图7。在图6 中,空操作语句是用来对多个文件的保存进行同步。 例如,有文件1 和文件2 需要保存,先将文件1 的内容写入Flash 中,文件1 路径下的目录节点被添加到未保存队列中,再将文件2 的内容写入Flash 中,文件2 路径下的目录节点也被添加到未保存队列中,最后将未保存队列中的所有节点都写入Flash 中。 这样,如果同一路径下的两个文件同时存盘,可避免路径下的相同目录节点被写入两次,从而提高了效率。 不足之处在于,如果很多文件同时存盘,会导致索引节点在一段时间内都无法写入Flash 存储器,有断电丢失的危险。 但对于一般嵌入式系统来说,很少会碰到这种情况。 当进行Flash存储器擦写时,在取块队列首节点至索引节点写入完成这段时间内都不允许进行其他Flash 存储器的写入操作,这是为了保证数据的完整性,同时也提高了文件系统的稳定性。无目录文件系统的优化许多嵌入式系统设计中虽没有目录管理的要求,但是对执行效率和资源消耗的要求较高。 对于不要求有目录管理的精简文件系统,在设计时也进行了优化。 精简文件系统在Flash 中的存储格式与上述设计相同,文件系统中的所有文件信息都保存在索引节点的根目录信息表中。 精简文件系统在内存中的映象则要简单很多,只包含索引节点中的信息,包括簇状态表、下一个擦除块、下一个新节点的标号和根目录信息,而不用为每个文件都建立内存中的映象,节省大量的内存空间。 文件的编辑存盘过程简化为:打开文件、编辑、将文件写入Flash 存储器、将修改后的索引节点写入Flash 存储器。 擦写则只需通过查询根目录信息表中的各个目录项,将块中的所有文件节点写入空簇即可。在无目录管理的情况下,精简文件系统占用的内存资源可以减少,操作也可便捷,提高了效率。 对于大量只需要按名存取的简单文件管理的小型嵌入式系统而言,针对Flash 存储器的简单文件系统将占用资源少,执行效率高,有很大的应用价值。嵌入式文件系统实现及性能分析该文件系统的实现采用了分层方法,分为3 层4 个部分:应用程序接口、文件系统核心、操作系统调用接口、Flash 存储器驱动,实现结构见图8。ic72新闻中心实现平台中RTOS 为μC/OSOII 实时操作系统,CPU 使用三星S4510B作为处理器,Flash 存储器芯片为FUJ ITSU 的29LV160 TE。 针对不同的实时操作系统和Flash 存储器芯片需要实现不同的操作系统接口和Flash 存储器驱动。针对μC/ OSOII 编写操作系统调用接口,包括5个函数: ①系统调用接口初始化FS_Sys_Interface_Init ( ) ,创建互斥信号量和内存分区; ② Flash 写入关闭FS_Sys_Write_Lock ( ) ,禁止Flash 写入操作,调用μC/OS-II 中OSMutePend ( ) ; ③ Flash写入打开FS_Sys_Write_Unlock ( ) ,重新允许Flash 写入操作,调用μC/OS-II 中OSMutePost() ; ④内存空间申请FS_Sys_Mem_Alloc( ) 和内存空间添加FS_Sys_Mem_Add ( ) , 都调用OSMemGet ( ) 来完成; ⑤内存空间释放FS_Sys_Mem_Free ( ) ,调用OSMemPut ( ) 完成,将申请的内存块全部释放。针对29LV160 TE 这款Flash 存储器芯片,定义一个FlashDef 结构体的全局变量, 用于存储Flash 器件信息,并且编写针对此款Flash 的块擦写函数FS_Device_Sector_Erase ( ) 和数据写入函数FJ FS_Device_Write ( ) 。完成这两部分的实现后,该系统就可运行调试。 测试应用程序接口(API) 。 应该提供的各部分功能,并在突然断电情况下,测试文件系统的恢复情况。无目录管理的精简文件系统的载入,可在2μs内完成,文件写入耗时主要为闪存的等待时间,系统本身只占用不到200 个字节的内存,产生的代码段大小为7 K。 完整的文件系统载入时,需要建立内存中映象,耗时根据文件数量的多少而不同,一般为10μs ,产生的代码段大小为11 K。 系统写入效率较高,在无目录管理的配置下尤其明显。 试验中系统在多次断电的情况下,系统仍能恢复至上次存盘的状态,虽会导致个别文件未更新,但不会导致文件系统崩溃。间的关系熟悉吗?的和(并)。互斥事件(互不相容事件

㈥ windows7支持的文件系统有哪些

windows7支持哪三种文件系统:

1,FAT

FAT文件系统诞生于1977年,它最初是为软盘设计的文件系统,但是后来随着微软推出dos和win 9x系统,FAT文件系统经过适配被逐渐用到了硬盘上,并且在那时的20年中,一直是主流的文件系统。

后来随着硬件技术的进步,硬盘的容量也越来越大,这种文件格式逐渐被扩展了,出现了FAT12,FAT16,FAT32等文件系统,甚至后来还出现了FAT64的文件系统。

2,NTFS

NTFS全称是New Technology File System,它是一种比FAT32功能更加强大的文件系统。

从windows 2000之后的windows系统的默认文件系统都是NTFS,而且这些windows系统只能够安装在NTFS格式的磁盘上。

㈦ 设计一个分布式文件系统应注意什么

分布式文件系统设计主要关注几个方面:设计特点、分布式能力、性能、容灾、维护和扩展、成本 分布式文件系统主要关键技术:全局名字空间、缓存一致性、安全性、可用性、可扩展性

㈧ 如何设计一个小型文件系统,提供创建、打开、读、写、关闭、删除文件的功能。

这是一个简单的程序设计问题,学过c的人都会。在c 里面提供了功能强大的文件管理函数,fopen ,fread,fwrite,fclose,等,多看一下,自己就会了

㈨ 为linux系统设计一个简单的二级文件系统。要求做到以下几点:

#include<stdio.h> #include<string.h> #include<stdlib.h> #define MEM_D_SIZE 1024*1024 //总磁盘空间为1M#define DISKSIZE 1024//磁盘块的大小1K#define DISK_NUM 1024//磁盘块数目1K#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//路径最大长度为1KB#define MSD 5//最大子目录数5#define MOFN 5//最大文件深度为5#define MAX_WRITE 1024*128//最大写入文字长度128KB struct 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; }

㈩ 如何在U盘实现自己设计的文件系统

下载个U工具就可以随心所欲地设计了,网络下力托软件网站就有下载,打开网站就可以看到

未经允许不得转载:山九号 » 设计文件系统|用c++设计一个简单的二级文件系统

赞 (0)