虚拟文件系统的实现
- 格式:doc
- 大小:107.00 KB
- 文档页数:24
linux vfs实现原理摘要:1.虚拟文件系统(VFS)简介2.VFS 的实现原理a.VFS 的主要组件b.VFS 的文件系统接口c.VFS 的文件操作实现d.VFS 的目录操作实现e.VFS 的异步I/O 实现3.VFS 的优势和应用场景4.VFS 的未来发展正文:虚拟文件系统(VFS)是Linux 内核中的一种重要机制,它为文件系统提供了统一的接口,使得用户空间程序能够方便地访问不同类型的文件系统。
VFS 的实现原理复杂,但它的核心思想是将实际的文件系统抽象成一个统一的虚拟文件系统,为用户空间程序提供一致的访问接口。
VFS 的主要组件包括文件系统层、VFS 层和用户空间层。
文件系统层是实际存储数据的层次,它包括各种类型的文件系统,如ext2、ext3、NTFS 等。
VFS 层是文件系统层和用户空间层之间的接口,它负责处理文件系统层提供的服务,并将其转换为用户空间程序能够理解的形式。
用户空间层是用户空间程序与VFS 之间的接口,它负责处理用户程序的文件操作请求,并将其转换为VFS 能够理解的形式。
VFS 的文件系统接口包括文件操作和目录操作。
文件操作包括打开、读取、写入、关闭等操作,目录操作包括目录创建、删除、遍历等操作。
VFS 的文件操作实现主要通过文件系统层提供的系统调用实现,而目录操作实现则通过VFS 层提供的虚拟目录实现。
VFS 的异步I/O 实现是VFS 的另一个重要特性。
它允许用户空间程序在执行文件操作时,同时执行其他操作,而不需要等待文件操作完成。
VFS 的异步I/O 实现是通过文件系统层提供的异步I/O 功能实现的。
VFS 的优势在于它能够为用户空间程序提供一致的文件系统接口,使得用户空间程序能够方便地访问不同类型的文件系统。
同时,VFS 的实现原理也使得它能够灵活地处理各种复杂的文件系统操作。
因此,VFS 在Linux 系统中得到了广泛的应用。
VFS 的未来发展主要取决于Linux 内核的发展。
linux vfs实现原理-回复什么是Linux VFS?Linux VFS(Virtual File System,虚拟文件系统)是Linux操作系统中的核心组件之一,它提供了一个统一的接口,使得用户空间程序可以通过相同的方式来操作不同类型的文件系统。
使用Linux VFS,用户可以对文件和目录进行创建、删除、重命名、读写等基本操作,而无需关注底层文件系统的具体实现细节。
Linux VFS的实现原理:Linux VFS的实现原理主要包括以下几个方面:1. Linux VFS的核心结构:Linux VFS的核心结构是以inode(index node,索引节点)为基础的。
每个文件或目录在Linux文件系统中都对应一个唯一的inode,inode包含了文件或目录的属性信息以及指向该文件数据块的指针。
通过inode,Linux VFS可以追踪文件和目录的位置和属性,实现对其进行各种操作。
2. 文件系统抽象层:Linux VFS实现了一个文件系统抽象层,用于屏蔽不同文件系统的差异性。
通过定义一组统一的接口,将不同文件系统的具体实现细节隐藏起来,使得上层应用程序可以通过相同的方式来操作不同类型的文件系统。
文件系统抽象层提供了一系列的操作函数,如文件打开、读写、关闭等,供上层应用程序调用。
3. 虚拟文件系统和挂载:Linux VFS实现了一个虚拟文件系统(Virtual File System),通过挂载(mount)操作将各个具体文件系统与虚拟文件系统关联起来。
挂载操作可以将一个具体文件系统的根目录挂载到虚拟文件系统的某个目录上,从而使得该具体文件系统的内容在虚拟文件系统中可见。
这样,用户就可以通过虚拟文件系统的接口来操作具体文件系统中的文件和目录。
4. 命名空间(Namespace)的实现:Linux VFS通过命名空间的概念来解决不同文件系统之间的冲突和隔离问题。
每个命名空间都有自己的根目录,文件系统中的文件和目录都是相对于该根目录进行操作的。
linux vfs实现原理(原创版)目录1.虚拟文件系统(VFS)的概念与作用2.VFS 的原理与实现3.VFS 在 Linux 中的应用4.VFS 的未来发展趋势正文虚拟文件系统(VFS,Virtual Filesystem)是 Linux 中一种重要的文件系统技术。
VFS 可以为系统中的各种文件系统提供统一的访问接口,使得不同的文件系统在操作系统中的表现更加一致。
在 VFS 的实现过程中,它采用了一种虚拟化的技术,将实际存在的文件系统抽象成一种可以在操作系统中统一管理的形式。
VFS 的原理与实现主要基于 Linux 内核中的文件系统驱动。
在Linux 内核中,文件系统驱动负责实现对各种文件系统的支持。
VFS 作为文件系统驱动的一部分,主要负责将用户的文件系统请求转换为具体的文件系统操作。
这个过程中,VFS 会将用户请求中的文件路径转换为实际文件系统的路径,然后通过文件系统驱动执行相应的文件系统操作。
在 Linux 中,VFS 的应用十分广泛。
除了支持多种文件系统之外,VFS 还可以支持块设备、管道和 socket 等其他类型的设备。
这使得Linux 系统在处理不同类型的设备时,可以采用一致的方式进行管理。
另外,VFS 还可以实现文件系统的挂载和卸载,方便用户对文件系统进行管理和维护。
随着计算机技术的不断发展,VFS 在未来也将面临一些新的挑战。
例如,随着文件系统越来越大,如何高效地管理大量的文件和目录将成为VFS 需要解决的问题。
此外,随着云计算和虚拟化技术的发展,VFS 还需要支持更多的虚拟化功能,以满足用户对文件系统的多样化需求。
总之,虚拟文件系统(VFS)是 Linux 中一种重要的文件系统技术,它为系统中的各种文件系统提供了统一的访问接口。
VFS 的实现原理主要基于 Linux 内核中的文件系统驱动,并且在 Linux 中有着广泛的应用。
enigma virtual box实现原理
Enigma Virtual Box是一种将应用程序和依赖项封装为单个可执行文件的工具。
它通过创建一个虚拟文件系统和注册表来实现。
首先,Enigma Virtual Box将目标应用程序及其依赖项(如DLL文件、配置文件等)复制到一个虚拟文件系统中。
这个虚拟文件系统是一个隐藏在一个文件中的文件系统,用户可以将其视为一个虚拟硬盘。
接下来,Enigma Virtual Box会修改目标应用程序的可执行文件,以便它能够在运行时访问虚拟文件系统。
这包括将文件访问路径替换为虚拟文件系统路径,并将文件读取和写入操作重定向到虚拟文件系统。
Enigma Virtual Box还会修改目标应用程序的注册表项,以便它能够在运行时访问虚拟注册表。
这包括将注册表路径替换为虚拟注册表路径,并将注册表读取和写入操作重定向到虚拟注册表。
当用户运行经过Enigma Virtual Box封装的可执行文件时,它会创建一个虚拟执行环境。
这个虚拟执行环境在运行时将虚拟文件系统和虚拟注册表暴露给目标应用程序,使其能够正常运行。
通过这种方式,Enigma Virtual Box实现了将应用程序及其依
赖项打包为单个可执行文件的功能,减少了文件和注册表的碎片化,并增强了应用程序的安全性和移植性。
虚拟化文件系统VMFS有损数据恢复方法实现及原理张宇(北亚企安科技(北京)有限公司,北京100094)摘要:该文介绍了一种利用VMFS固有系统信息完成数据丢失或损坏的情况下的数据提取方法。
首先阐述VMFS的文件系统结构、各管理组件特性、功能和数据寻址原理,然后介绍各类常见数据丢失情况所导致的底层数据变化方式,最后给出应对于各种数据丢失场景下的恢复方案。
关键词:VMFS;ESXi;数据恢复技术中图分类号:TP3文献标识码:A文章编号:1009-3044(2019)36-0059-02开放科学(资源服务)标识码(OSID):自1946年世界上首台电子计算机问世至今已有60年之久,在此期间硬件发展速度遵循甚至超出摩尔定律的预期。
如此快速的发展让计算机在高精尖领域大放光彩,但是在对性价比要求较高的民用领域,高性能物理硬件性能过剩和老旧硬件性能不足等问题逐年彰显。
在20世纪六七十年代IBM发明了操作系统虚拟机技术,此技术利用大型机高性能硬件的快速反应速度,在单台服务器上安装多个操作系统并发提供给不同用户使用,虚拟化操作系统雏形初现。
但这种技术只适用于大型机,应用范围很小,无法满足中小型企业的需求。
直到1999年,VMware公司在x86平台上推出商业虚拟化软件ESXi,虚拟化技术才开始普及到计算机领域内的各行各业,此虚拟化平台所使用的文件系统正是VMFS。
由于其应用范围的不断扩展,在使用过程中由于不可抗力和人为因素导致的数据丢失案例也呈现出上升趋势。
根据故障发生频率,本文着重讨论误删除和格式化这两种情况下的数据恢复方案。
1VMFS卷结构及各组件功能VMFS在历史上共出现了三个版本,分别为VMFS3、VMFS5和VMFS6,当前市面上常见版本为VMFS5。
在VMFS5文件系统内,存储结构按照其在卷内出现顺序大致可分为三个区域:保留区、元文件区以及用户数据区。
保留区一般用0填充不使用,元文件区主要存储管理VMFS卷的各元文件,包括vh.sf、.fdc.sf、.sbc.sf、pbc.sf、.fbb.sf、.pb2.sf。
linux vfs实现原理-回复Linux VFS(Virtual File System,虚拟文件系统)是一个抽象层,用于将不同的文件系统类型(如ext4、NTFS等)统一管理,并提供了一套统一的系统调用接口,使用户和应用程序可以访问不同文件系统的文件。
实现原理方面,Linux VFS具有以下核心机制和组件。
1. 文件抽象:文件系统在Linux中以文件的形式表示,无论是硬盘上的真实文件还是其他设备文件。
VFS为不同的文件系统定义了通用的文件抽象结构,即`struct file`,它包含了文件的元数据信息(如文件大小、创建时间等),以及指向文件操作方法的函数指针(如读、写、截断等操作)。
通过这种方式,VFS 将不同文件系统的文件统一管理和操作。
2. 虚拟目录结构:VFS还定义了虚拟目录结构,用于组织文件系统中的文件和目录。
Linux 通过树状的虚拟目录结构来表示整个文件系统,并提供了一套系统调用(如`chdir`、`mkdir`、`unlink`等)用于操作目录结构。
VFS将这些系统调用转换成相应的文件系统特定操作,以实现对不同文件系统目录的访问和管理。
3. 文件描述符:Linux通过文件描述符(`file descriptor`)来表示打开的文件。
每个进程的文件描述符表(`file descriptor table`)维护了所有打开文件的引用计数、文件位置等信息。
VFS利用文件描述符来实现文件的共享和访问控制,以及文件位置的管理。
4. 文件系统类型注册:Linux支持多种文件系统类型,如ext4、NTFS、FAT等。
VFS提供了一套接口用于注册和管理这些文件系统类型。
每个文件系统都需要实现一组特定的函数(如`read_superblock`、`read_inode`等),提供文件系统内部数据结构的读取和操作。
VFS将不同文件系统注册到系统中,并通过文件系统类型进行区分和调度。
5. 挂载和命名空间:在Linux中,外部设备、文件系统都通过挂载(`mount`)的方式加入到整个文件系统中。
ecryptfs 实现方式(原创实用版)目录1.Ecryptfs 简介2.Ecryptfs 的实现方式3.Ecryptfs 的优势与不足正文1.Ecryptfs 简介Ecryptfs 是一种基于 Linux 内核的加密文件系统,它的设计初衷是为了提供一种安全、高效、易于使用的文件加密解决方案。
Ecryptfs 的特点在于其透明性,用户可以在不改变原有文件操作习惯的情况下,对文件进行加密保护。
2.Ecryptfs 的实现方式Ecryptfs 的实现方式主要包括以下几个方面:(1)虚拟文件系统:Ecryptfs 在 Linux 内核中注册为一个虚拟文件系统,用户可以像操作其他文件系统一样,对 Ecryptfs 进行挂载、卸载等操作。
(2)加密算法:Ecryptfs 支持多种加密算法,如 AES、Blowfish 等。
用户可以根据自己的需求,选择合适的加密算法对文件进行加密。
(3)文件加密与解密:Ecryptfs 通过内核模块实现文件的加密与解密。
当用户对文件进行读取操作时,Ecryptfs 会自动将文件解密后返回给用户;当用户对文件进行写入操作时,Ecryptfs 会将用户写入的数据进行加密后存储。
(4)密钥管理:Ecryptfs 采用 GNU 隐私保护器(GnuPG)作为密钥管理工具,用户可以使用 GnuPG 对加密密钥进行创建、导入、导出、删除等操作。
3.Ecryptfs 的优势与不足(1)优势:Ecryptfs 具有较高的安全性,可以有效防止数据泄露;支持多种加密算法,满足不同用户的需求;具有较好的透明性,用户使用习惯不受影响。
(2)不足:Ecryptfs 的性能相对较低,因为每次文件读写操作都需要进行加密解密;Ecryptfs 对系统资源有一定的需求,可能影响系统性能。
总之,Ecryptfs 作为一种基于 Linux 内核的加密文件系统,通过其独特的实现方式,为用户提供了一种安全、高效、易用的文件加密解决方案。
理解操作系统中的虚拟文件系统和文件描述符一、介绍在操作系统中,虚拟文件系统(VFS)和文件描述符是两个关键概念。
虚拟文件系统是操作系统提供给用户应用程序的抽象出的文件系统接口,而文件描述符则是应用程序用于操作文件的标识符。
虚拟文件系统提供了一种统一的方式来访问不同类型的存储设备和文件系统,而文件描述符则用于表示文件在应用程序中的打开和操作。
二、虚拟文件系统1.虚拟文件系统的定义虚拟文件系统是一种操作系统层面的抽象,它提供了一种统一的接口来访问不同类型的存储设备和文件系统。
它隐藏了不同文件系统之间的实现细节,使得用户应用程序可以通过同样的方式来操作不同类型的文件。
2.虚拟文件系统的组成虚拟文件系统由三个主要组件组成:文件对象(file object)、文件系统对象(file system object)和虚拟文件系统接口(VFS interface)。
-文件对象是操作系统中表示打开文件的数据结构,它包含了文件的状态信息和指向文件系统对象的指针。
-文件系统对象是表示文件系统的数据结构,它包含了文件系统的具体实现和方法。
-虚拟文件系统接口是用户应用程序与操作系统之间进行交互的接口,它定义了一组标准的文件操作函数,如打开、读取、写入、关闭等。
3.虚拟文件系统的优点虚拟文件系统具有以下几个优点:-提供了统一的文件系统接口,使得用户应用程序可以通过同样的方式来操作不同类型的文件。
-隐藏了不同文件系统之间的实现细节,使得用户应用程序可以更加方便地进行文件操作。
-允许用户应用程序在不同文件系统之间进行文件的复制、移动等操作,而不需要了解文件系统的具体细节。
三、文件描述符1.文件描述符的定义文件描述符是一个用于表示打开文件或其他设备的整数。
在Unix-like操作系统中,每个进程都有一个文件描述符表,其中包含了与它打开的文件或设备相关的信息。
2.文件描述符的使用文件描述符是应用程序与操作系统进行文件操作的接口,它通过系统调用来进行打开、读取、写入、关闭等操作。
操作系统虚拟文件系统实验报告1. 引言本报告旨在总结并分析我们小组在操作系统虚拟文件系统实验中的经验和发现。
操作系统是计算机系统中非常重要的一个组成部分,负责管理计算机硬件和软件资源。
而虚拟文件系统(Virtual File System,VFS)则是操作系统中一个关键的抽象层,为用户和应用程序提供了统一的文件操作接口。
通过对虚拟文件系统的实验,我们深入了解了操作系统的内部实现原理,加深了对文件系统的理解。
2. 实验目的本次实验的主要目的是对操作系统的虚拟文件系统进行实践探索,通过实际操作和观察,加深对虚拟文件系统的理解,并熟悉常见的文件系统操作。
3. 实验环境我们使用了一台以Linux操作系统为基础的计算机作为实验平台,并采用虚拟机技术搭建了多个虚拟机实例,以便进行并行的多任务操作。
4. 实验过程与结果4.1 文件系统的创建与挂载首先,我们使用命令行工具创建了一个新的文件系统,并将其挂载到操作系统的指定目录上。
通过这一步骤,我们成功地在操作系统上创建了一个虚拟的文件系统,并使其能够被操作系统识别并访问。
4.2 文件的创建、读取和写入在实验过程中,我们创建了多个文件,并测试了文件的读取和写入功能。
我们发现,在虚拟文件系统下,文件的读取和写入操作是非常高效和稳定的。
通过在文件中写入不同类型的数据并进行读取,我们验证了文件系统的正确性和可靠性。
4.3 目录的创建和遍历除了文件操作外,我们还对虚拟文件系统中的目录进行了创建和遍历实验。
通过创建多层次的目录结构并遍历其中的所有文件和子目录,我们验证了虚拟文件系统对目录的管理和访问功能。
4.4 文件系统的扩展与压缩为了进一步探索虚拟文件系统的性能和可扩展性,我们对文件系统进行了动态扩展和压缩实验。
通过添加和删除大量文件,我们观察到文件系统的性能表现良好,并且在文件数量不断增加的情况下能够有效地管理和访问这些文件。
5. 实验总结与思考通过本次虚拟文件系统的实验,我们对操作系统的底层实现原理有了更深入的了解。
enigma virtual box原理Enigma Virtual Box是一款虚拟化软件,它将应用程序的所有文件和注册表项打包成单个可执行文件,从而实现应用程序的独立运行。
下面将介绍Enigma Virtual Box的工作原理。
首先,Enigma Virtual Box通过两个主要组件来实现应用程序的虚拟化,即虚拟文件系统(Virtual File System,VFS)和虚拟注册表(Virtual Registry)。
VFS负责虚拟化应用程序的文件系统,而虚拟注册表负责虚拟化应用程序的注册表项。
当用户将一个应用程序打包成可执行文件后,Enigma Virtual Box会将应用程序的所有文件添加到虚拟文件系统中。
在运行时,VFS会拦截对文件系统的访问请求,并根据应用程序的虚拟化配置将请求重新定向到虚拟文件系统中的相应文件。
虚拟化配置是Enigma Virtual Box中的一项关键功能,它允许用户根据自己的需求对文件系统的访问进行配置。
例如,用户可以选择将某些文件保留在物理文件系统中,而将其他文件添加到虚拟文件系统中。
用户还可以将虚拟文件系统中的文件重定向到不同的位置,以便实现文件的动态加载。
类似地,虚拟注册表会拦截对注册表的访问请求,并将其重新定向到应用程序的虚拟化注册表中。
用户可以使用Enigma Virtual Box提供的工具来编辑虚拟注册表,添加、删除或修改注册表项。
在运行时,Enigma Virtual Box会在计算机的内存中创建一个虚拟环境,将应用程序的虚拟文件系统和虚拟注册表加载到其中。
这样,应用程序就可以在独立的运行环境中执行,而不会对计算机的实际文件系统和注册表产生影响。
Enigma Virtual Box还提供了一些其他功能,例如自动缓存和虚拟文件系统保护。
自动缓存可以提高应用程序的运行性能,减少对物理文件系统的访问次数。
虚拟文件系统保护可以防止应用程序在虚拟文件系统外部创建、修改或删除文件。
虚拟文件系统的实现-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结构体。
vfat文件系统实现原理(实用版)目录1.VFAT 文件系统的概述2.VFAT 文件系统的基本原理3.VFAT 文件系统的特点4.VFAT 文件系统的应用5.总结正文一、VFAT 文件系统的概述VFAT(Virtual File Allocation Table)文件系统是一种虚拟文件分配表文件系统,是 Windows 操作系统中 FAT 文件系统的一个扩展。
VFAT 文件系统主要用于存储 Windows 操作系统中的虚拟磁盘映像文件,这些文件通常用于仿真磁盘空间。
与传统的 FAT 文件系统相比,VFAT 文件系统具有更高的灵活性和更好的性能。
二、VFAT 文件系统的基本原理VFAT 文件系统的基本原理是通过虚拟文件分配表(Virtual File Allocation Table)实现对磁盘空间的管理。
虚拟文件分配表是一个数据结构,用于记录磁盘上已分配的文件空间和未分配的文件空间。
VFAT 文件系统在磁盘上划分出一块空间来存储虚拟文件分配表,然后根据虚拟文件分配表来分配和释放磁盘空间。
三、VFAT 文件系统的特点1.灵活性:VFAT 文件系统可以根据需要动态地调整虚拟文件分配表的大小,从而实现对磁盘空间的灵活管理。
2.高性能:VFAT 文件系统通过使用更高效的磁盘空间分配算法,提高了磁盘空间的利用率,从而提高了系统的性能。
3.易于管理:VFAT 文件系统提供了一些方便的管理工具,例如磁盘管理器,可以帮助用户轻松地管理磁盘空间。
四、VFAT 文件系统的应用VFAT 文件系统主要应用于以下场景:1.虚拟磁盘映像文件:在 Windows 操作系统中,虚拟磁盘映像文件通常使用 VFAT 文件系统进行存储。
2.磁盘分区:用户可以通过磁盘管理器创建 VFAT 文件系统的分区,从而实现对磁盘空间的灵活管理。
3.兼容性:VFAT 文件系统可以与传统的 FAT 文件系统兼容,使得用户可以在不同的操作系统中访问相同的磁盘空间。
基于vfs实现⾃⼰的⽂件系统1.Linux ⽂件系统组成结构linux⽂件系统有两个重要的特点:⼀个是⽂件系统抽象出了⼀个通⽤⽂件表⽰层——虚拟⽂件系统或称做VFS。
另外⼀个重要特点就是它的⽂件系统⽀持动态安装(或说挂载等),⼤多数⽂件系统都可以作为根⽂件系统的叶⼦节点被挂在到根⽂件⽬录树下的⼦⽬录上。
1.1.虚拟⽂件系统虚拟⽂件系统为⽤户空间程序提供了⽂件系统接⼝。
系统中所有⽂件系统不但依赖VFS共存,⽽且也依靠VFS系统协同⼯作。
通过虚拟⽂件系统我们可以利⽤标准的UNIX⽂件系统调⽤对不同介质上的不同⽂件系统进⾏读写操作。
虚拟⽂件系统的⽬的是为了屏蔽各种各样不同⽂件系统的相异操作形式,使得异构的⽂件系统可以在统⼀的形式下,以标准化的⽅法访问、操作。
实现虚拟⽂件系统利⽤的主要思想是引⼊⼀个通⽤⽂件模型——该模型抽象出了⽂件系统的所有基本操作(该通⽤模型源于Unix风格的⽂件系统),⽐如读、写操作等。
同时实际⽂件系统如果希望利⽤虚拟⽂件系统,即被虚拟⽂件系统⽀持,也必须将⾃⾝的诸如“打开⽂件”、“读写⽂件”等操作⾏为以及“什么是⽂件”,“什么是⽬录”等概念“修饰”成虚拟⽂件系统所要求的(定义的)形式,这样才能够被虚拟⽂件系统⽀持和使⽤。
我们可以借⽤⾯向对象的思想来理解虚拟⽂件系统,可以想象成⾯向对象中的多态。
1.2.虚拟⽂件系统的相关对象虚拟⽂件系统的核⼼概念1、 VFS 通过树状结构来管理⽂件系统,树状结构的任何⼀个节点都是“⽬录节点”2、树状结构具有⼀个“根节点”3、 VFS 通过“超级块”来了解⼀个具体⽂件系统的所有需要的信息。
具体⽂件系统必须先向VFS注册,注册后,VFS就可以获得该⽂件系统的“超级块”。
4、具体⽂件系统可被安装到某个“⽬录节点”上,安装后,具体⽂件系统才可以被使⽤5、⽤户对⽂件的操作,就是通过VFS 的接⼝,找到对应⽂件的“⽬录节点”,然后调⽤该“⽬录节点”对应的操作接⼝。
VFS虚拟⽂件系统⼀、VFS简介Linux 采⽤ Virtual Filesystem(VFS)的概念,通过内核在物理存储介质上的⽂件系统和⽤户之间建⽴起⼀个虚拟⽂件系统的软件抽象层,使得 Linux 能够⽀持⽬前绝⼤多数的⽂件系统,不论它是 windows、unix 还是其他⼀些系统的⽂件系统,都可以挂载在 Linux 上供⽤户使⽤。
VFS 在 Linux 中是⼀个处理所有 unix ⽂件系统调⽤的软件层,同时给不同类型的⽂件系统提供⼀个统⼀的接⼝。
VFS ⽀持以下归类的三种类型的⽂件系统:(1) 磁盘⽂件系统,存储在本地磁盘、U盘、CD等的⽂件系统,它包含各种不同的⽂件系统格式,⽐如 windows NTFS、VFAT,BSD 的UFS,CD的 CD-ROM 等(2) ⽹络⽂件系统,它们存储在⽹络中的其他主机上,通过⽹络进⾏访问,例如 NFS(3) 特殊⽂件系统,例如 /proc、sysfs 等VFS 背后的思想就是建⽴⼀个通⽤的⽂件模型,使得它能兼容所有的⽂件系统,这个通⽤的⽂件模型是以 Linux 的⽂件系统 EXT 系列为模版构建的。
每个特定的⽂件系统都需要将它物理结构转换为通⽤⽂件模型。
例如,通⽤⽂件模型中,所有的⽬录都是⽂件,它包含⽂件和⽬录;⽽在其他的⽂件类型中,⽐如 FAT,它的⽬录就不属于⽂件,这时,内核就会在内存中⽣成这样的⽬录⽂件,以满⾜通⽤⽂件模型的要求。
同时,VFS 在处理实际的⽂件操作时,通过指针指向特定⽂件的操作函数。
可以认为通⽤⽂件模型是⾯向对象的设计,它实现了⼏个⽂件通⽤模型的对象定义,⽽具体的⽂件系统就是对这些对象的实例化。
通⽤⽂件模型包含下⾯⼏个对象:(1) superblock 存储挂载的⽂件系统的相关信息(2) inode 存储⼀个特定⽂件的相关信息(3) file 存储进程中⼀个打开的⽂件的交互相关的信息(4) dentry 存储⽬录和⽂件的链接信息(5) 这⼏个通⽤⽂件模型中的对象之间的关系如下图所⽰:VFS 除了提供⼀个统⼀⽂件系统接⼝,它还提供了名为 dentry cache 的磁盘缓存,⽤于加速⽂件路径的查找过程。
文章主题:VFS页面缓冲实现原理一、VFS页面缓冲概述在操作系统中,虚拟文件系统(VFS)是一个重要的组成部分,它负责管理文件系统和存储设备的访问。
其中,VFS页面缓冲是VFS中的关键功能之一,它用于缓存文件系统中的页面,以提高对文件的读写效率。
在本文中,我们将深入探讨VFS页面缓冲的实现原理,以便更深入地理解该功能。
二、VFS页面缓冲实现原理的初步了解在文件系统中,为了实现文件的读写操作,需要将文件从磁盘中读取到内存中进行处理,然后再将结果写回到磁盘中。
这个过程中,频繁的磁盘读写操作会影响文件系统的性能。
为了解决这个问题,VFS引入了页面缓冲机制,将文件的页面(通常是4KB大小的单位)缓存到内存中,以减少对磁盘的访问次数。
三、VFS页面缓冲的实现原理1. 缓冲区管理:VFS页面缓冲需要管理内存中的缓冲区,用于存储文件页面的数据。
在这个过程中,需要实现缓冲区的分配、释放以及相关的数据结构管理。
2. 页面替换算法:当内存中的缓冲区不足时,需要根据一定的替换算法来确定哪些页面需要被替换出去。
常见的页面替换算法包括最近最少使用(LRU)算法、先进先出(FIFO)算法等。
3. 页面同步:在进行文件的读写操作时,需要保持内存中的页面和磁盘中的数据一致。
VFS页面缓冲需要实现页面同步的机制,在写回磁盘时保证数据的完整性。
四、VFS页面缓冲的优化与改进1. 热点页面缓存:针对常被访问的页面,可以采取预取或预热的方式将其缓存到内存中,以提高对这些页面的访问速度。
2. 多级缓存:对于大型文件系统,可以采用多级缓存的方式来提高缓冲效率,例如将常用的页面放在较快的缓存区中,将不常用的页面放在较慢但容量更大的缓存区中。
五、总结与展望通过对VFS页面缓冲实现原理的探讨,我们可以更深入地理解文件系统中缓存机制的重要性和作用。
在未来,随着大规模数据存储和处理需求的增加,VFS页面缓冲将面临更多的挑战和机遇。
希望在未来的研究与实践中,能够进一步优化和改进VFS页面缓冲的性能,以更好地满足不断增长的文件系统需求。
渤海大学操作系统课程设计实验报告书题目:虚拟文件系统的实现题目编号:院系:软件服务与外包学院班级:11级2班小组成员:陈镜欢学号:*********王晨学号:*********2013-06-30目录一、课程设计任务划分 (1)二、基本原理 (1)2.1主要操作函数 (1)2.2数据结构 (1)2.3算法流程图 (3)三、基本思路 (4)3.1 设计简介 (4)3.2 设计方案论述 (4)3.3 文件基本操作 (4)四、调试及实验结果 (5)运行结果分析 (8)五、个人体会 (8)一、课程设计任务划分陈镜欢:主要编写代码熟悉课题的任务和要求,查阅相关文献和资料,并做好编码准备,调试,验收王晨:程序编码、调试和测试,书写报告二、基本原理2.1主要操作函数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();2.2数据结构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; /*当前打文件的数目*/};2.3算法流程图三、基本思路3.1 设计简介本系统是模拟实现多用户多目录的文件系统,在系统出现登录后 ,输入用户与口令,在用户登录系统后,可建立文件卷,将用户输入的文件保存在指定的文件中。
1 设计本系统是模拟实现多用户多目录的文件系统,在系统出现登录后 ,输入用户与口令,在用户登录系统后,可建立文件卷,将用户输入的文件保存在指定的文件中。
系统的命令与其命令的具体实现,此模拟系统共提供了上述命令,并根据命令的含义与要求,用C++编程来完成所有具体操作。
该系统可以模拟完成用户的登陆和验证,列出文件和目录,新建目录,改变目录,创立和编写文件,删除文件和退出系统等功能2 设计方案本文件系统采用两级目录,其中第一级对应于用户账号,第二级对应于用户帐号下的文件。
另外,为了简便文件系统未考虑文件共享,文件系统安全以及管道文件与设备文件等特殊内容。
首先应确定文件系统的数据结构:主目录、子目录及活动文件等。
主目录和子目录都以文件的形式存放于磁盘,这样便于查找和修改。
用户创建的文件,可以编号存储于磁盘上。
如:file0,file1,file2…并以编号作为物理地址,在目录中进行登记。
3 文件基本操作创建文件:创建一个新文件时,系统首先要为新文件申请必要的外存空间,并在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");}else{printf("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();}}}。