精华内容
下载资源
问答
  • vfsStream :流包装器的虚拟文件系统有助于单元测试模拟真正的文件系统。它可用于任何单元测试框架,比如PHPUnit)或SimpleTest。
  • 虚拟文件系统

    千次阅读 2010-06-01 19:19:00
    通过所谓的虚拟文件系统概念,Linux使用与其他Unix变体相同的方式设法支持多种文件系统类型。 虚拟文件系统所隐含的思想是把表示很多不同种类文件系统的共同信息放入内核;其中有一个字段或函数来支持Linux所支持的...

    现在我们的主流价值观是社会和谐、世界和谐。同样,Linux成功的关键因素之一是它具有与其他操作系统和谐共存的能力。你能够透明地安装具有其他操作系统文件格式的磁盘或分区,这些操作系统如Windows、其他版本的Unix,甚至像Amiga那样的市场占有率很低的系统。通过所谓的虚拟文件系统概念,Linux使用与其他Unix变体相同的方式设法支持多种文件系统类型。

    虚拟文件系统所隐含的思想是把表示很多不同种类文件系统的共同信息放入内核;其中有一个字段或函数来支持Linux所支持的所有实际文件系统所提供的任何操作。对所调用的每个读、写或其他函数,内核都能把它们替换成支持本地Linux文件系统、NTFS文件系统,或者文件所在的任何其他文件系统的实际函数。

    1 虚拟文件系统概述


    虚拟文件系统(Virtual Filesystem)也可以称之为虚拟文件系统转换(Virtual Filesystem Switch,VFS),是一个内核软件层,用来处理与Unix标准文件系统相关的所有系统调用。其健壮性表现在能为各种文件系统提供一个通用的接口。

    例如,假设一个用户输入以下shell命令:
    $ cp /floppy/TEST /tmp/test

    其中/floppy是MS-DOS磁盘的一个安装点,而/tmp是一个标准的第二扩展文件系统(second Extended Filesystom, Ext2)的目录。正如图(a)所示,VFS是用户的应用程序与文件系统实现之间的抽象层。因此,cp程序并不需要知道/floppy/TEST 和 /tmp/test是什么文件系统类型。相反,cp程序直接与VFS交互,这是通过Unix程序设计人员都熟悉的普通系统调用来进行的。cp的执行代码如图(b)所示:


    VFS支持的文件系统可以划分为三种主要类型:

    磁盘文件系统

    这些文件系统管理在本地磁盘分区中可用的存储空间或者其他可以起到磁盘作用的设备(比如说一个USB闪存)。VFS支持的基于磁盘的某些著名文件系统还有:

    - Linux使用的文件系统,如广泛使用的第二扩展文件系统(Ext2),新近的第三扩展文件系统(Third Extended Filesystem,Ext3)及Reiser文件系统(ReiserFS)

    - Unix家族的文件系统,如sysv文件系统(System V、Coherent、Xenix)、UFS(BSD、Solaris、NEXTSTEP),MINIX文件系统及VERITAS VxFS(SCO UnixWare)。

    - 微软公司的文件系统,如MS-DOS、VFAT(Windows 95及随后的版本)及NTFS(Windows NT以及随后的版本)。

    - IS09660 CD-ROM文件系统(以前的High Sierra文件系统)和通用磁盘格式(UDF)的DVD文件系统。

    - 其他有专利权的文件系统,如HPFS(IBM公司的OS/2)、HFS(苹果公司的Macintosh)、AFFS(Amiga公司的快速文件系统)以及ADFS(Acorn 公司的磁盘文件归档系统)。

    - 起源于非Linux系统的其他日志文件系统,如IBM的JFS和SGI的XFS。

    网络文件系统


    这些文件系统允许轻易地访问属于其他网络计算机的文件系统所包含的文件。虚拟文件系统所支持的一些著名的网络文件系统有:NFS、Coda、AFS(Andrew文件系统)、CIFS(用于Microsoft Windows的通用网络文件系统)以及NCP(Novell公司的NetWare Core Protocol)。

    特殊文件系统

    这些文件系统不管理本地或者远程磁盘空间。/proc、/sys、/dev等文件系统是特殊文件系统的一个典型范例。

    Unix的目录建立了一棵根目录为“/”的树。根目录包含在根文件系统(root filesystem)中,在Linux中这个根文件系统通常就是Ext2或Ext3类型。其他所有的文件系统都可以被“安装”在根文件系统的子目中。当一个文件系统被安装在某一个目录上时,在父文件系统中的目录内容不再是可访问的了,因为任何路径(包括安装点),都将引用已安装的文件系统。但是,当被安装文件系统卸载时,原目录的内容又可再现。

    所以,Unix文件系统的一个重要特点就是可以由系统管理员用来隐藏文件,他们只需把一个文件系统安装在要隐藏文件的目录中即可。

    基于磁盘的文件系统通常存放在块设备中,如硬盘、软盘或者CD-ROM。Linux VFS的一个有用特点是能够处理如/dev/loop0这样的虚拟块设备,这种设备可以用来安装普通文件所在的文件系统。作为一种可能的应用,用户可以保护自己的私有文件系统,因为可以通过把自己文件系统的加密版本存放在一个普通文件中来实现。

    第一个虚拟文件系统包含在1986年由Sun公司发布的SunOS操作系统中。从那时起,多数UNIX文件系统都包含VFS。然而,Linux的VFS支持最广泛的文件系统。

    2 通用文件模型


    VFS所隐含的主要思想在于引入了一个通用的文件模型(common file model),这个模型能够表示所有支持的文件系统。该模型严格反映传统Unix文件系统提供的文件模型。这并不奇怪,因为Linux希望以最小的额外开销运行它的本地文件系统。不过,要实现每个具体的文件系统,必须将其物理组织结构转换为虚拟文件系统的通用文件模型。

    例如在通用文件模型中,每个目录被看作一个文件,可以包含若干文件和其他的子目录。但是,存在几个非Unix的基于磁盘的文件系统,它们利用文件分配表(File Allocation Table,FAT)存放每个文件在目录树中的位置,在这些文件系统中,存放的是目录而不是文件。为了符合VFS的通用文件模型,对上述基于FAT的文件系统的实现,Linux必须在必要时能够快速建立对应于目录的文件。这样的文件只作为内核内存的对象而存在。

    从本质上说,Linux内核不能对一个特定的函数进行硬编码来执行诸如read()或ioctl()这样的操作,而是对每个操作都必须使用一个指针,指向要访问的具体文件系统的适当函数。

    为了进一步说明这一概念,参见前面的那个图,其中显示了内核如何把read()转换为专对MS-DOS文件系统的一个调用。应用程序对read()的调用引起内核调用相应的sys_read()服务例程,这与其他系统调用完全类似。我们在本章后面会看到,文件在内核内存中是由一个file数据结构来表示的。这种数据结构中包含一个称为f_op的字段,该字段中包含一个指向专对MS-DOS文件的函数指针,当然还包括读文件的函数。

    sys_read()查找到指向该函数的指针,并调用它。这样一来,应用程序的read()就被转化为相对间接的调用:
    file->f_op->read(…);

    与之类似,write()操作也会引发一个与输出文件相关的Ext2写函数的执行。简而言之,内核负责把一组合适的指针分配给与每个打开文件相关的file变量,然后负责调用针对每个具体文件系统的函数(由f_op字段指向)。

    你可以把通用文件模型看作是面向对象的,在这里,对象是一个软件结构,其中既定义了数据结构也定义了其上的操作方法。出于效率的考虑,Linux的编码并未采用面向对像的程序设计语言(比如C++)。因此对象作为普通的C数据结构来实现,数据结构中指向函数的字段就对应于对象的方法。

    通用文件模型由下列对象类型组成:

    超级块对象(superblock object):存放已安装文件系统的有关信息。对基于磁盘的文件系统,这类对象通常对应于存放在磁盘上的文件系统控制块(filesystem control block)。

    索引节点对象(inode object):存放关于具体文件的一般信息。对基于磁盘的文件系统,这类对象通常对应于在磁盘上的文件控制块(file control block)。每个索引节点对象都有一个索引节点号,这个节点号唯一地标识文件系统中的文件。

    文件对象(file object):存放打开文件与进程之间进行交互的有关信息。这类信息仅当进程访问文件期间在于内核内存中。

    目录项对象(dentry object):存放目录项(也就是文件的特定名称)与对应文件进行链接的有关信息。每个磁盘文件系统都以自己特有的方式将该类信息存在磁盘上。

    下图所示是一个简单的示例,说明进程怎样与文件进行交互。


    三个不同进程已经打开同一个文件,其中两个进程使用同一个硬链接。在这种情况下,其中的每个进程都使用自己的文件对象,但只需要两个目录项对象,每个硬链接对应一个目录项对象。这两个目录项对象指向同一个索引节点对象,该索引节点对象标识超级块对象,以及随后的普通磁盘文件。

    VFS除了能为所有文件系统的实现提供一个通用接口外,还具有另一个与系统性能相关的重要作用,那就是一些文件相关数据结构的磁盘高速缓存。例如最近最常使用的目录项对象被放在所谓目录项高速缓存(dentry cache)的磁盘高速缓存中,从而加速从文件路径名到最后一个路径分量的索引节点的转换过程。

    一般说来,磁盘高速缓存(disk cache)属于软件机制,它允许内核将原本存在磁盘上的某些信息保存在RAM中,以便对这些数据的进一步访问能快速进行,而不必慢速访问磁盘本身。

    注意,磁盘高速缓存不同于硬件高速缓存或内存高速缓存,后两者都与磁盘或其他设备无关。硬件高速缓存是一个快速静态RAM,它加快了直接对内存,这样的慢速动态RAM的请求。内存高速缓存是一种软件机制,引入它是为了绕过内核内存分配器(slab分配器)。

    除了目录项高速缓存和索引结点高速缓存之外,Linux还使用其他磁盘高速缓存。其中最重要的一种就是所谓的页高速缓存,我们将在本专题中中进行详细介绍。

    3 VFS所处理的系统调用


    下表列出了VFS的系统调用,这些系统调用涉及文件系统、普通文件、目录文件以及符号链接文件:

    系统调用名

    说明

    mount( ) umount( ) umount2( )

    安装/卸载文件系统

    sysfs( )

    获取文件系统信息

    statfs( ) fstatfs( ) statfs64( ) fstatfs64( )

    ustat( )

    获取文件系统统计信息

    chroot( ) pivot_root( )

    更改根目录

    chdir( ) fchdir( ) getcwd( )

    对当前目录进行操作

    mkdir( ) rmdir( )

    创建/删除目录

    getdents( ) getdents64( ) readdir( ) link( )

    unlink( ) rename( ) lookup_dcookie( )

    对目录项进行操作

    readlink( ) symlink( )

    对软链接进行操作

    chown( ) fchown( ) lchown( ) chown16( )

    fchown16( ) lchown16( )

    更改文件所有者性

    chmod( ) fchmod( ) utime( )

    更改文件属性

    stat( ) fstat( ) lstat( ) access( ) oldstat( ) oldfstat( ) oldlstat( ) stat64( ) lstat64( )

    fstat64( )

    读取文件状态

    open( ) close( ) creat( ) umask( )

    打开/关闭/创建文件

    dup( ) dup2( ) fcntl( ) fcntl64( )

    对文件描述符进行操作

    select( ) poll( )

    等待一组文件描述符上发生的事件

    truncate( ) ftruncate( ) truncate64( )

    ftruncate64( )

    更改文件长度

    lseek( ) _llseek( )

    更改文件指针

    read( ) write( ) readv( ) writev( ) sendfile( ) sendfile64( ) readahead( )

    进行文件I/O 操作

    io_setup( ) io_submit( ) io_getevents( ) io_cancel( ) io_destroy( )

    异步I/O (允许多个读和写请求)

    pread64( ) pwrite64( )

    搜索并访问文件

    mmap( ) mmap2( ) munmap( ) madvise( ) mincore( )

    remap_file_pages( )

    处理文件内存映射

    fdatasync( ) fsync( ) sync( ) msync( )

    同步文件数据

    flock( )

    处理文件锁

    setxattr( ) lsetxattr( ) fsetxattr( ) getxattr( ) lgetxattr( ) fgetxattr( ) listxattr( ) llistxattr( ) flistxattr( ) removexattr( ) lremovexattr( ) fremovexattr( )

    处理文件扩展属性



    另外还有少数几个由VFS处理的其他系统调用,诸如ioperm()、ioctl()、pipe()和mknod(),涉及设备文件和管道文件,这些将在后续博文中讨论。最后一组由VFS处理的系统调用,诸如socket()、connect()和bind()属于套接字系统调用,并用于实现网络功能。与表中列出的系统调用还对应的一些内核服务例程,我们会在后面的博文中陆续进行讨论。

    前面我们已经提到,VFS是应用程序和具体文件系统之间的一层。不过,在某些情况下,一个文件操作可能由VFS本身去执行,无需调用低层函数。例如,当某个进程关闭一个打开的文件时,并不需要涉及磁盘上的相应文件,因此VFS只需释放对应的文件对象。类似地,当系统调用lseek()修改一个文件指针,而这个文件指针是打开文件与进程交互所涉及的一个属性时,VFS就只需修改对应的文件对象,而不必访问磁盘上的文件,因此,无需调用具体文件系统的函数。从某种意义上说,可以把VFS看成“通用”文件系统,它在必要时依赖某种具体文件系统。

     

    展开全文
  • 操作系统实习,模拟操作系统中的文件系统,可实现多shell脚本操作,具体有操作说明和功能菜单帮助文件
  • FAT16虚拟文件系统

    2010-03-14 11:11:38
    虚拟文件系统 虚拟文件系统 虚拟文件系统 虚拟文件系统 虚拟文件系统
  • C语言实现建议的虚拟文件系统,完成dir,mv,copy等命令,基于文件模拟一个电脑磁盘上的文件管理。C语言实现建议的虚拟文件系统,完成dir,mv,copy等命令,基于文件模拟一个电脑磁盘上的文件管理。
  • 实现unix虚拟文件系统

    2017-07-12 20:29:02
    实现unix虚拟文件系统 C++实现 操作系统课设 多用户、多级目录结构文件系统的设计与实现
  • 本文详细分析了文件系统、文件结构、虚拟文件系统的定义及作用、VFS与文件系统的关系。分析当中加入了很多自己的理解,重点分析了文件的结构,虚拟文件系统(VFS)与文件系统、用户程序的关系,分析的比较通俗。

    文件系统

          文件系统是对一个存储设备上的数据和元数据进行组织的机制。可以理解成文件系统是对文件的存储、读取、管理等。

         从系统的角度,文件系统是对文件存储空间进行组织分配、负责文件的存储并对存入的文件进行保护和检索的系统。

           用户的角度,当我们需要保存数据或信息时候,我们只需要提供存放文件的路径和文件名,借助文件系统就可以在磁盘上面找到该文件的物理位置。

     说明:

         Linux系统中存在很多的文件系统,例如常见的:ext2,ext3,sysfs,rootfs,proc等。每一个文件系统都是相互独立的,都有自己的组织方式。

     文件结构

       文件结构是文件存放在磁盘等存储设备的组织方法。顾名思义文件结构,联想我们通常所说的装修房子的结构,就是房子的房间布局、规划。同理,文件结构就是怎样将不同的文件有机的组织起来,Linux系统中文件很多,像系统的配置文件、设备文件等,这些必须要有一种结构将他们组织起来,以方便我们管理,这里的文件结构就是起这个作用。

     虚拟文件系统

           虚拟文件系统,作为内核子系统,为用户空间程序提供文件和文件系统相关的接口。虚拟文件系统(VFS是物理文件系统与服务之间的一个接口层,它对Linux的每个文件系统的所有细节进行抽象,使得不同的文件系统在Linux核心以及系统中运行的其他进程看来,都是相同的。严格说来,VFS并不是一种实际的文件系统。它只存在于内存不存在于任何外存空间VFS在系统启动时建立,在系统关闭时消亡。

       说明:

    ⑴ 虚拟,两字说明文件系统在磁盘(或者其他存储介质上)并没有对应的存储信息。准确的讲VFS是一种软件机制,只存在内存中。

    “虚”的VFS的信息都源于“实”的文件系统,所以VFS必须承载各种文件系统的共有属性。

    这些“实”的文件系统只有安装在系统中,VFS才予以认可VFS只管理挂载在系统的实际的文件系统。

    这些“实”的文件系统是按需被挂载的,并不是一次性挂载。

        作用:

    通过虚拟文件系统,程序可以利用标准的Unix系统调用对不同的文件系统,甚至不同介质上的文件系统进行读写操作。

    ⑵通过VFS,它将不同的文件系统抽象后采用统一的方式进行操作。这样用户上层应用就可以采用统一的系统调用而不用考虑底层不同的调用方法。

    ⑶内核在VFS的底层文件系统接口上建立了一个抽象层,其定义了所以文件系统都支持的、基本、概念上的接口和数据结构,所以能链接各种各样的文件系统。

    ⑷总的来说,VFS是一种软件机制VFS是文件系统组织管理中的一个抽象层

      

                                                          

                                                                                VFS与具体文件系统之间的关系

        自己类比理解:

           虚拟文件系统给用户空间提供统一的接口,在这里我们可以把虚拟文件系统这个机制理解成淘宝这个平台,把用户空间理解成买家。淘宝(VFS)负责将整个购物流程抽象成简单的接口,提供相应的接口给买家(用户空间),这些接口我们可以理解成付款接口:支付宝网银接口、商家网站地址、商品搜索查询接口、快递流程查询接口等。买家不用去管这些商品怎么被用户搜索到,不用管钱是怎样在支付宝中流转、不用管物流等。

        这里的具体的文件系统可以理解成各种不同的商家,这些是实实在在的,他们有具体的货物,没有货物谈何交易。淘宝(VFS)这个机制利用抽象层,使得不同的商家,无论是卖零食、电器、书籍等可以有机的连接起来。

        总的来说,内核通过VFS(淘宝平台)可以毫不费力把任何文件系统(不同商家)协同起来工作,并且给用户空间(买家)提供接口(购物入口)。

     参考文献:

     Linux 内核设计与实现

     

    展开全文
  • C++模拟文件系统

    2018-06-28 16:39:26
    1)用高级语言编写和调试一个简单的文件系统模拟文件管理的工作过程。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。 (2)要求设计一个 n个用户的文件系统,每次用户可保存m个文件,用户在一次...
  • 使用C语言编写程序,模拟一个简单的文件系统,要求如下: (1) 文件系统的组织结构参考ext2文件系统 (2) 创建一个“disk.os”文件,大小为4MB,用该文件模拟外存。 (3) 最后应生成一个可执行文件“myfs”,...
  • 自己在操作系统课程设计时做的模拟实现VFS系统,供大家参考。(里面有报告和源代码,标准C++代码可以在Linux...摘要:本文利用虚拟文件系统(VFS)思想,建立一个统一的接口框架。并基于此接口实现了一个简单的文件系统。
  • 1、课程设计的目的 本课程设计是学生学习完《操作系统...了解EXT2文件系统,设计一个类EXT2型文件系统,所设计的文件系统要具备文件系统格式化、用户登录、用户注销、显示目录内容、文件创建、文件删除、目录创建...

    1、课程设计的目的

    本课程设计是学生学习完《操作系统原理及应用》课程后,进行的一次全面的综合训练,通过课程设计,让学生更好地掌握操作系统的原理及实现方法,加深对操作系统基础理论和重要算法的理解,加强学生的动手能力。

    2、课程设计的内容及要求

    了解EXT2文件系统,设计一个类EXT2型文件系统,所设计的文件系统要具备文件系统格式化、用户登录、用户注销、显示目录内容、文件创建、文件删除、目录创建和目录删除等功能,创建的文件不要求格式和内容,但要有相应的权限控制。

    可以用一个文件或在内存中开辟一个虚拟磁盘空间来模拟文件系统的磁盘空间,要注意目录结构的设计和磁盘空间的分配与回收。程序能够在Linux环境运行并验证结果。

    点击此处下载文档和源码

     

     

    展开全文
  • 虚拟文件系统 虚拟文件系统(VFS)或虚拟文件系统开关是更具体的文件系统之上的抽象层。 VFS的目的是允许客户端应用程序以统一的方式访问不同类型的具体文件系统。 虚拟文件系统向用户提供了与基于UNIX的文件系统...
  • vfsStream vfsStream是虚拟文件系统的流包装,在模拟真实文件系统的单元测试中可能会有所帮助。 它可以与任何单元测试框架一起使用,例如PHPUnit或SimpleTest。 Documentat vfsStream vfsStream是虚拟文件系统的流...
  • 基于虚拟文件系统proc的财富分发程序基于虚拟文件系统proc的财富分发程序基于虚拟文件系统proc的财富分发程序基于虚拟文件系统proc的财富分发程序基于虚拟文件系统proc的财富分发程序基于虚拟文件系统proc的财富分发...
  • 这是一个用Java实现的一个虚拟文件系统,支持多用户使用,模拟了数据分块,实现了一些基本的文件目录操作,如创建目录,目录跳转,目录的重命名,复制拷贝,删除,以及文件的创建,编辑,重命名和删除,查看目录和...
  • 一个用Java实现的一个虚拟文件系统,支持多用户使用,模拟了数据分块,实现了一些基本的文件目录操作,如创建目录,目录跳转,目录的重命名,复制拷贝,删除,以及文件的创建,编辑,重命名和删除,查看目录和文件的...
  • 一个操作系统课程设计,使用java语言模拟磁盘文件系统实现,实现了FAT算法
  • 【Linux】Linux的虚拟文件系统

    千次阅读 2018-08-04 20:01:27
    Linux的虚拟文件系统与实际文件系统的关系如下所示:   VFS的原理 各种文件系统之所以有区别,就在于它们的目录文件结构各不相同,随之而来的也就是对文件目录的操作函数也不相同。对于前者可以在保留原系统...

    Linux的虚拟文件系统与实际文件系统的关系如下所示:

     

    VFS的原理

    各种文件系统之所以有区别,就在于它们的目录文件结构各不相同,随之而来的也就是对文件目录的操作函数也不相同。对于前者可以在保留原系统目录结构的基础上,再构建一个新的统一的目录文件结构,而这个新目录文件中的信息是通过提取原系统目录文件信息进行重新组织来建立的。这样,用户面对的就不再是五花八门的目录文件,而是一个统一的目录文件。

    为了让不同文件系统操作函数实现一个统一的操作界面,VFS利用函数指针,因为函数指针实质上就是对函数的一次抽象,如下:

    从上图可见,用户在使用函数指针f()调用函数时,真正被调用的函数为该指针指向的函数,而指针f只是一个替身,或者说,它只是实际函数的一个虚拟表示。换句话说,通过同一个f可以调用不同的函数,至于调用的是哪一个函数,则取决于操作系统使哪个函数与指针f相关联。这也就是说,函数指针可以为多个不同的函数提供一个统一界面。

    使用上述方法,Linux为虚拟文件系统构建了如下结构的函数指针集,以统一操作界面:

    struct file_operations {
    	struct module *owner;
    	loff_t (*llseek) (struct file *, loff_t, int);
    	ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
    	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
    	ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
    	ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
    	int (*readdir) (struct file *, void *, filldir_t);
    	unsigned int (*poll) (struct file *, struct poll_table_struct *);
    	int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
    	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
    	long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
    	int (*mmap) (struct file *, struct vm_area_struct *);
    	int (*open) (struct inode *, struct file *);
    	int (*flush) (struct file *, fl_owner_t id);
    	int (*release) (struct inode *, struct file *);
    	int (*fsync) (struct file *, struct dentry *, int datasync);
    	int (*aio_fsync) (struct kiocb *, int datasync);
    	int (*fasync) (int, struct file *, int);
    	int (*lock) (struct file *, int, struct file_lock *);
    	ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
    	unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
    	int (*check_flags)(int);
    	int (*flock) (struct file *, int, struct file_lock *);
    	ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
    	ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
    	int (*setlease)(struct file *, long, struct file_lock **);
    };

    用图形表示的file_operations如下所示:

    上图表示的函数指针表,就是VFS提供的用户与实际文件系统之间的接口。也就是说,不论使用什么文件系统,用户面对的都是指针表中的函数指针,至于具体的实际文件系统则取决于与函数指针相关联的具体函数。例如,如果VFS与Ext2系统挂接,那么用户对虚拟文件系统的操作就是对Ext2文件系统的操作,如下图所示:

    当然,如果实际文件系统不支持虚拟文件系统的某个操作,则该指针应该为NULL。

    从上述内容可知,虚拟文件系统既没有文件,也不直接管理文件,它只是用户与实际文件系统之间的接口。因此,它并不需要保存在永久存储介质中,只是在需要时由内核在内存中创建起来的一个文件系统,所以叫做虚拟文件系统。出于系统性能的考虑和设计者的偏好,Linux系统VFS的结构与Ext2基本相同。

    对于上述虚拟文件系统,《Linux内核源代码情景分析》中有如下描述:如果把内核比喻成计算机中的“母板”,把VFS比喻成“母板”上的一个“插槽”,那么每一个具体的文件系统就好像是一块“接口卡”。母板面对的是一个固定的插槽,而使用实际系统则是接口卡,插上什么卡就执行什么功能。

     

    VFS的超级块

    VFS超级块

    所有的实际文件系统,一旦被安装到系统上,就必须由系统在内存为其创建一个虚拟文件系统的超级块。这个超级块实质上也就是系统把实际文件系统超级块的相关信息提取出来(如Ext2的ext2_sb_info),再与虚拟系统所需要的通用信息拼接起来而形成的一个格式统一的超级块,它相当于一个实际文件系统在虚拟文件系统中的身份证。这个虚拟超级块包含如下信息:

    • 设备标识符。这是存储文件系统的物理设备的设备标识符;
    • 节点指针,包括安装i节点指针和覆盖i节点指针。其中,安装i节点指针指向被安装的子文件系统的第一个i节点;覆盖i节点指针则指向被安装文件系统的安装点;
    • 文件数据块的大小;
    • 超级块操作集。这是一组指向超级块操作例程的指针,VFS利用他们可以对超级块和i节点进行访问操作;
    • 所安装的文件系统的类型;
    • 被安装文件系统的一些私有信息。

    虚拟文件系统的超级块在文件include/linux/fs.h中定义如下:

    struct super_block {
    	struct list_head	s_list;		/* 文件超级块链表头指针 */
    	dev_t			s_dev;		/* 文件系统的块设备标识 */
    	unsigned long		s_blocksize;        //数据块的大小
    	unsigned char		s_blocksize_bits;        //块大小值所占的位数
    	unsigned char		s_dirt;        //该值若为1,标识该超级块已被修改
    	unsigned long long	s_maxbytes;	/* 文件大小的最大值 */
    	struct file_system_type	*s_type;        //已注册文件系统的链表指针
    	const struct super_operations	*s_op;        //指向超级块操作函数集的指针
    	struct dquot_operations	*dq_op;
     	struct quotactl_ops	*s_qcop;
    	const struct export_operations *s_export_op;
    	unsigned long		s_flags;
    	unsigned long		s_magic;
    	struct dentry		*s_root;
    	struct rw_semaphore	s_umount;
    	struct mutex		s_lock;
    	int			s_count;
    	int			s_need_sync_fs;
    	atomic_t		s_active;
    #ifdef CONFIG_SECURITY
    	void                    *s_security;
    #endif
    	struct xattr_handler	**s_xattr;
    
    	struct list_head	s_inodes;	/* all inodes */
    	struct list_head	s_dirty;	/* dirty inodes */
    	struct list_head	s_io;		/* parked for writeback */
    	struct list_head	s_more_io;	/* parked for more writeback */
    	struct hlist_head	s_anon;		/* anonymous dentries for (nfs) exporting */
    	struct list_head	s_files;
    	/* s_dentry_lru and s_nr_dentry_unused are protected by dcache_lock */
    	struct list_head	s_dentry_lru;	/* unused dentry lru */
    	int			s_nr_dentry_unused;	/* # of dentry on lru */
    
    	struct block_device	*s_bdev;
    	struct mtd_info		*s_mtd;
    	struct list_head	s_instances;
    	struct quota_info	s_dquot;	/* Diskquota specific options */
    
    	int			s_frozen;
    	wait_queue_head_t	s_wait_unfrozen;
    	char s_id[32];				/* Informational name */
    
    	void 			*s_fs_info;	/* 指向实际文件系统超级块内核信息结构的指针 */
    	fmode_t			s_mode;
    	struct mutex s_vfs_rename_mutex;	/* Kludge */
    	u32		   s_time_gran;
    	char *s_subtype;
    	char *s_options;
    	struct list_head s_async_list;
    };

    虚拟文件系统的超级块,既包含虚拟文件系统的通用管理信息,也包含具体文件系统的私有信息。其中,结构的指针s_fs_info就指向具体实际文件系统的私有信息,该信息被保存在内存的一个结构中。

    例如:当虚拟文件系统在与Ext2文件系统对接时,指针s_fs_info就指向Ext2文件系统的私有信息结构struct ext2_sb_info。即系统在安装Ext2系统时,会在内存中创建一个struct ext2_sb_info结构实例,将磁盘文件系统Ext2超级块struct ext2_super_block的部分私有信息提取到该结构,并将结构与VFS超级块指针s_fs_info关联起来,如下图所示:

    结构struct ext2_sb_info的定义如下:

    struct ext2_sb_info {
    	unsigned long s_frag_size;	    /* 碎片大小 */
    	unsigned long s_frags_per_block;    /* 每块碎片的数目 */
    	unsigned long s_inodes_per_block;    /* 每块节点数 */
    	unsigned long s_frags_per_group;    /* 块组中的碎片数 */
    	unsigned long s_blocks_per_group;    /* 块组中块的数量 */
    	unsigned long s_inodes_per_group;    /* 块组中的节点数目 */
    	unsigned long s_itb_per_group;	    /* 块组中节点表所占用的块数 */
    	unsigned long s_gdb_count;	    /* 块组描述符表所占用的块数 */
    	unsigned long s_desc_per_block;	    /* 块组描述符数 */
    	unsigned long s_groups_count;	    /* 块组数 */
    	unsigned long s_overhead_last;  /* 块缓冲区指针 */
    	unsigned long s_blocks_last;    /* 指向缓冲区中超级块的指针 */
    	struct buffer_head * s_sbh;	    /* 指向缓冲区中组描述符表的指针 */
    	struct ext2_super_block * s_es;	    /* Pointer to the super block in the buffer */
    	struct buffer_head ** s_group_desc;
    	unsigned long  s_mount_opt;
    	unsigned long s_sb_block;
    	uid_t s_resuid;
    	gid_t s_resgid;
    	unsigned short s_mount_state;
    	unsigned short s_pad;
    	int s_addr_per_block_bits;
    	int s_desc_per_block_bits;
    	int s_inode_size;            //节点大小
    	int s_first_ino;            //第一个节点号
    	spinlock_t s_next_gen_lock;
    	u32 s_next_generation;
    	unsigned long s_dir_count;
    	u8 *s_debts;
    	struct percpu_counter s_freeblocks_counter;
    	struct percpu_counter s_freeinodes_counter;
    	struct percpu_counter s_dirs_counter;
    	struct blockgroup_lock *s_blockgroup_lock;
    
    	spinlock_t s_rsv_window_lock;
    	struct rb_root s_rsv_window_root;
    	struct ext2_reserve_window_node s_rsv_window_head;
    };

    VFS超级块的操作函数集

    依照Linux的设计思想,Linux把有关文件系统超级块的操作函数集中地列写在一个封装了超级块操作函数指针的结构super_operations中,并用VFS超级块结构中的域s_op指向这个结构:

    struct super_operations {
       	struct inode *(*alloc_inode)(struct super_block *sb);
    	void (*destroy_inode)(struct inode *);
    
       	void (*dirty_inode) (struct inode *);
    	int (*write_inode) (struct inode *, int);
    	void (*drop_inode) (struct inode *);
    	void (*delete_inode) (struct inode *);
    	void (*put_super) (struct super_block *);
    	void (*write_super) (struct super_block *);
    	int (*sync_fs)(struct super_block *sb, int wait);
    	int (*freeze_fs) (struct super_block *);
    	int (*unfreeze_fs) (struct super_block *);
    	int (*statfs) (struct dentry *, struct kstatfs *);
    	int (*remount_fs) (struct super_block *, int *, char *);
    	void (*clear_inode) (struct inode *);
    	void (*umount_begin) (struct super_block *);
    
    	int (*show_options)(struct seq_file *, struct vfsmount *);
    	int (*show_stats)(struct seq_file *, struct vfsmount *);
    #ifdef CONFIG_QUOTA
    	ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
    	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
    #endif
    	int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
    };

    这个结构与前面介绍的struct file_operations一样,相当于具体文件系统超级块所使用的安装在内核上的“插槽”。

     

    VFS的dentry结构

    结构dentry是实际文件系统的目录项在虚拟文件系统VFS中的对应物,实质上就是前面所讲的目录缓冲区。当系统访问一个具体文件时,会根据这个文件在磁盘上的目录在内存中创建一个dentry结构,它除了要存放文件目录信息之外,还要存放有关文件路径的一些动态信息。

    例如:它建立了文件名与节点inode之间的联系,保存了目录项与其父、子目录之间的关系。之所以建立这样的一个文件目录的对应物,是为了同一个目录被再次访问时,其相关信息就可以直接由dentry获得,而不必再次重复访问磁盘。

    VFS的dentry结构

    结构dentry在文件include/linux/dcache.h中定义如下:

    struct dentry {
    	atomic_t d_count;
    	unsigned int d_flags;		/* 记录目录项被引用次数的计数器 */
    	spinlock_t d_lock;		/* 目录项的标志 */
    	int d_mounted;
    	struct inode *d_inode;		/* 与文件名相对应的inode */
    
    	struct hlist_node d_hash;	/* 目录项形成的散列表 */
    	struct dentry *d_parent;	/* 指向父目录项的指针 */
    	struct qstr d_name;        //包含文件名的结构
    
    	struct list_head d_lru;		/* 已经没有用户使用的目录项的链表 */
    	union {
    		struct list_head d_child;	/* 父目录的子目录项形成的链表 */
    	 	struct rcu_head d_rcu;
    	} d_u;
    	struct list_head d_subdirs;	/* i节点别名的链表 */
    	struct list_head d_alias;	/* inode alias list */
    	unsigned long d_time;		/* used by d_revalidate */
    	const struct dentry_operations *d_op;        //指向dentry操作函数集的指针
    	struct super_block *d_sb;	/* 目录树的超级块,即本目录项所在目录树的根 */
    	void *d_fsdata;			/* 文件系统的特定数据 */
    
    	unsigned char d_iname[DNAME_INLINE_LEN_MIN];	/* 短文件名 */
    };
    

    结构中的域d_name是qstr类型的结构。该结构的定义如下:

    struct qstr {
    	unsigned int hash;            //文件名
    	unsigned int len;            //文件名长度
    	const unsigned char *name;        //散列值
    };

    内核通过维护一个散列表dentry_hashtable来管理dentry。系统一旦在内存中建立一个dentry,该dentry结构就会被链入散列表的某个队列中。

    结构中的域d_count记录了本dentry被访问的次数。当某个dentry的d_count的值为0时,就意味着这个dentry结构已经没有用户使用了,这时这个dentry会被d_lru链入一个由系统维护的另一个队列dentry_unused中。由于内核从不删除曾经建立的dentry,于是,同一个目录被再次访问时,其相关信息就可以直接由dentry获得,而不必重复访问存储文件系统的外存。

    另外,当本目录项有父目录节点时,其dentry结构通过域d_child挂入父目录项的子目录d_subdirs队列中,同时使指针d_parent指向父目录的dentry结构。若本目录有子目录,则将它们挂接在域d_subdirs指向的队列中。

    dentry的操作函数

    为了对dentry结构进行操作,系统定义了一个dentry操作函数集,目录项dentry中的域d_op就指向封装了这些操作函数指针的结构:

    struct dentry_operations {
    	int (*d_revalidate)(struct dentry *, struct nameidata *);        //判断目录项是否有效
    	int (*d_hash) (struct dentry *, struct qstr *);            //生成一个散列值
    	int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);        //比较两个文件名
    	int (*d_delete)(struct dentry *);        //删除count为0的dentry
    	void (*d_release)(struct dentry *);        //释放一个dentry对象
    	void (*d_iput)(struct dentry *, struct inode *);        //丢弃目录项对应的inode
    	char *(*d_dname)(struct dentry *, char *, int);
    };

    由于在结构中的所有域都是操作函数的指针,因此这个结构相当于一个函数跳转表,系统通过这个函数跳转表来调用所要使用的函数。因此,这个结构相当于具体文件系统目录项所使用的安装在内核的“插槽”。

     

    VFS的i节点

    VFS的i节点简介

    前面谈到,i节点是文件的控制块,它存放文件的基本信息。不同文件系统的i节点结构是不同的,甚至在一些一体化目录结构的文件系统(例如FAT系统)中根本就没有i节点的概念,所以在使用某一个实际文件系统时,内核必须按照虚拟文件系统i节点的格式在内存创建一个VFS的i节点,并根据该实际文件系统的静态数据来填写这个i节点。

    VFS的i节点结构在文件include/linux/fs.h中定义如下:

    struct inode {
    	struct hlist_node	i_hash;            //指向散列表的指针
    	struct list_head	i_list;            //指向i节点链表的这孩子很
    	struct list_head	i_sb_list;
    	struct list_head	i_dentry;            //指向dentry链表的指针
    	unsigned long		i_ino;            //i节点号
    	atomic_t		i_count;            //记录使用本节点进程数目的计数器
    	unsigned int		i_nlink;            //节点连接的别名的数目
    	uid_t			i_uid;            //文件拥有者的标识号
    	gid_t			i_gid;            //文件拥有者所在组的标识号
    	dev_t			i_rdev;            //文件设备的标识号
    	u64			i_version;
    	loff_t			i_size;
    #ifdef __NEED_I_SIZE_ORDERED
    	seqcount_t		i_size_seqcount;
    #endif
    	struct timespec		i_atime;
    	struct timespec		i_mtime;
    	struct timespec		i_ctime;
    	unsigned int		i_blkbits;
    	blkcnt_t		i_blocks;
    	unsigned short          i_bytes;
    	umode_t			i_mode;
    	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
    	struct mutex		i_mutex;
    	struct rw_semaphore	i_alloc_sem;
    	const struct inode_operations	*i_op;        //指向i节点操作函数集的指针
    	const struct file_operations	*i_fop;	        /* 指向文件操作函数集的指针 */
    	struct super_block	*i_sb;            //指向文件系统超级块的指针
    	struct file_lock	*i_flock;
    	struct address_space	*i_mapping;        //指向下一个域i_data的指针
    	struct address_space	i_data;            //页缓冲区头结构
        void *generic_ip;            //指向实际文件节点信息结构的指针
    #ifdef CONFIG_QUOTA
    	struct dquot		*i_dquot[MAXQUOTAS];
    #endif
    	struct list_head	i_devices;
    	union {
    		struct pipe_inode_info	*i_pipe;
    		struct block_device	*i_bdev;
    		struct cdev		*i_cdev;
    	};
    	int			i_cindex;
    
    	__u32			i_generation;
    
    #ifdef CONFIG_DNOTIFY
    	unsigned long		i_dnotify_mask; /* Directory notify events */
    	struct dnotify_struct	*i_dnotify; /* for directory notifications */
    #endif
    
    #ifdef CONFIG_INOTIFY
    	struct list_head	inotify_watches; /* watches on this inode */
    	struct mutex		inotify_mutex;	/* protects the watches list */
    #endif
    
    	unsigned long		i_state;
    	unsigned long		dirtied_when;	/* jiffies of first dirtying */
    
    	unsigned int		i_flags;
    
    	atomic_t		i_writecount;
    #ifdef CONFIG_SECURITY
    	void			*i_security;
    #endif
    	void			*i_private; /* fs or device private pointer */
    };

    与VFS的超级块一样,VFS的i节点也是既包含虚拟文件系统的通用管理系统,又包含具体文件系统i节点的私有信息。其中,结构的指针generic_ip就指向了具体文件系统i节点的私有信息,该信息也被保存在内存的一个结构中。

    例如:当虚拟文件系统与Ext2文件系统对接时,指针generic_ip就指向Ext2文件系统的i节点信息结构ext2_inode_info。即系统在安装Ext2系统时,会在内存中创建一个ext2_inode_info结构实例,并将磁盘文件系统Ext2的i节点的部分私有信息提取到该结构。

    结构struct ext2_inode_info的代码如下:

    struct ext2_inode_info {
    	__le32	i_data[15];            //数据库块指针数组
    	__u32	i_flags;            //文件打开方式
    	__u32	i_faddr;
    	__u8	i_frag_no;            //第一个碎片号
    	__u8	i_frag_size;            //碎片大小
    	__u16	i_state;
    	__u32	i_file_acl;            //文件访问控制链表
    	__u32	i_dir_acl;
    	__u32	i_dtime;            //文件删除时间
    
    	__u32	i_block_group;            //文件所在块组号
    	struct ext2_block_alloc_info *i_block_alloc_info;
    
    	__u32	i_dir_start_lookup;
    #ifdef CONFIG_EXT2_FS_XATTR
    	struct rw_semaphore xattr_sem;
    #endif
    #ifdef CONFIG_EXT2_FS_POSIX_ACL
    	struct posix_acl	*i_acl;
    	struct posix_acl	*i_default_acl;
    #endif
    	rwlock_t i_meta_lock;
    
    	struct mutex truncate_mutex;
    	struct inode	vfs_inode;
    	struct list_head i_orphan;	/* unlinked but open inodes */
    };
    

    当虚拟文件与Ext2文件系统相关联时,VFS的索引节点如下图所示:

    VFS的i节点操作函数

    对于索引节点的操作函数封装在结构inode_operations中。该结构的定义如下:

    struct inode_operations {
    	int (*create) (struct inode *,struct dentry *,int, struct nameidata *);        //创建一个新i节点
    	struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);        //查找一个i节点的dentry
    	int (*link) (struct dentry *,struct inode *,struct dentry *);        //创建一个新的硬链接
    	int (*unlink) (struct inode *,struct dentry *);        //删除一个硬链接
    	int (*symlink) (struct inode *,struct dentry *,const char *);
    	int (*mkdir) (struct inode *,struct dentry *,int);
    	int (*rmdir) (struct inode *,struct dentry *);
    	int (*mknod) (struct inode *,struct dentry *,int,dev_t);
    	int (*rename) (struct inode *, struct dentry *,
    			struct inode *, struct dentry *);
    	int (*readlink) (struct dentry *, char __user *,int);
    	void * (*follow_link) (struct dentry *, struct nameidata *);
    	void (*put_link) (struct dentry *, struct nameidata *, void *);
    	void (*truncate) (struct inode *);
    	int (*permission) (struct inode *, int);
    	int (*setattr) (struct dentry *, struct iattr *);
    	int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
    	int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
    	ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
    	ssize_t (*listxattr) (struct dentry *, char *, size_t);
    	int (*removexattr) (struct dentry *, const char *);
    	void (*truncate_range)(struct inode *, loff_t, loff_t);
    	long (*fallocate)(struct inode *inode, int mode, loff_t offset,
    			  loff_t len);
    	int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
    		      u64 len);
    };
    

    inode的结构的指针i_op指向这个函数集。

    需要注意的是,inode结构还是要一个指向文件操作函数集struct file_operations的指针i_fop。

     

    文件缓冲区

    与内存相比,处理器读取磁盘数据的速度相当低,只相当于读取内存速度的千分之一,所以为了提高系统效率,Linux要在内存为最近访问的磁盘数据简历文件缓冲区。

    所谓文件缓冲区,就是一块内核内存区域。由于该区域是进程与磁盘之间起缓冲作用的中介,因此缓冲区在与磁盘交换信息时必须以块为访问单位。即从磁盘的角度看,这个缓冲区是磁盘数据块缓冲区,而从进程的角度看,则是页缓冲区。如下图所示:

    因此,内核中设置了两套用来管理缓冲区的数据结构。

    磁盘数据块缓冲区

    在Linux中,每一个磁盘数据块缓冲区用buffer_head结构来描述。buffer_head结构如下:

    struct buffer_head {
    	unsigned long b_state;		/* 缓冲区状态位图 */
    	struct buffer_head *b_this_page;/* 指向同一页面的缓冲块,形成环形链表 */
    	struct page *b_page;		/* 指向页缓冲指针 */
    
    	sector_t b_blocknr;		/* 逻辑块号 */
    	size_t b_size;			/* 块大小 */
    	char *b_data;			/* 指向数据块缓冲区的指针 */
    
    	struct block_device *b_bdev;        //指向块设备结构的指针
    	bh_end_io_t *b_end_io;		/* I/O completion */
     	void *b_private;		/* reserved for b_end_io */
    	struct list_head b_assoc_buffers; /* associated with another mapping */
    	struct address_space *b_assoc_map;	/* mapping this buffer is
    						   associated with */
    	atomic_t b_count;		/* 块引用计数 */
    };

    其中,域b_data是指向内存中磁盘块缓冲区的指针;域b_size表示缓冲区的大小。由于进程以页面为单位来访问缓冲区,所以结构中用域b_this_page把同一页面缓冲块组成了一个环形链表。

    另外,系统根据磁盘数据块缓冲区的使用状态将它们分别组成了多个队列。

    内存中的一个磁盘块缓冲区的队列示意图如下所示:

    磁盘数据块缓冲区是一种全局资源,可以被所有的文件系统共享使用。

    页缓冲区

    为了方便进程对文件的使用,并在需要时能把以块为单位的磁盘块缓冲区(块的大小一般为512字节)映射到以页为单位(页的大小一般4k)的用户空间,VFS还建立了页缓冲区。由于进程是通过VFS的i节点来访问文件的,因此,文件的页缓冲区也就被设置在inode结构中。

    inode结构中有一个指向自身的i_data域的指针i_mapping,这个i_data域是一个address_space的结构。而每一个页面的所有信息由struct page来描述,它有一个名称为mapping的域,这是一个指针,它指向一个struct address_space类型结构。

    缓冲区的数据结构struct address_space的主要内容如下:

    struct address_space {
    	struct inode		*host;		    /* 属主的索引节点 */
    	struct radix_tree_root	page_tree;	        /* 全部页面的radix数 */
    	spinlock_t		tree_lock;	        /* and lock protecting it */
    	unsigned int		i_mmap_writable;        /* count VM_SHARED mappings */
    	struct prio_tree_root	i_mmap;		    /* tree of private and shared mappings */
    	struct list_head	i_mmap_nonlinear;        /*list VM_NONLINEAR mappings */
    	spinlock_t		i_mmap_lock;	    /* protect tree, count, list */
    	unsigned int		truncate_count;	    /* Cover race condition with truncate */
    	unsigned long		nrpages;	    /* 占用的物理边框总数 */
    	pgoff_t			writeback_index;        /* writeback starts here */
    	const struct address_space_operations *a_ops;	    /* 页缓冲区操作函数集指针 */
    	unsigned long		flags;		    /* error bits/gfp mask */
    	struct backing_dev_info *backing_dev_info;     /* 预读信息 */
    	spinlock_t		private_lock;	    /* for use by the address_space */
    	struct list_head	private_list;	    /* 页缓冲区链表 */
    	struct address_space	*assoc_mapping;	    /* 相关缓存 */
    } __attribute__((aligned(sizeof(long))));

    页缓冲区与磁盘块缓冲区之间的关系如下图所示:

    依照Linux的一贯风格,Linux将缓冲区操作函数封装在如下的address_space_operations结构中:

    struct address_space_operations {
    	int (*writepage)(struct page *page, struct writeback_control *wbc);
    	int (*readpage)(struct file *, struct page *);
    	void (*sync_page)(struct page *);
    
    	/* Write back some dirty pages from this mapping. */
    	int (*writepages)(struct address_space *, struct writeback_control *);
    
    	/* Set a page dirty.  Return true if this dirtied it */
    	int (*set_page_dirty)(struct page *page);
    
    	int (*readpages)(struct file *filp, struct address_space *mapping,
    			struct list_head *pages, unsigned nr_pages);
    
    	int (*write_begin)(struct file *, struct address_space *mapping,
    				loff_t pos, unsigned len, unsigned flags,
    				struct page **pagep, void **fsdata);
    	int (*write_end)(struct file *, struct address_space *mapping,
    				loff_t pos, unsigned len, unsigned copied,
    				struct page *page, void *fsdata);
    
    	/* Unfortunately this kludge is needed for FIBMAP. Don't use it */
    	sector_t (*bmap)(struct address_space *, sector_t);
    	void (*invalidatepage) (struct page *, unsigned long);
    	int (*releasepage) (struct page *, gfp_t);
    	ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
    			loff_t offset, unsigned long nr_segs);
    	int (*get_xip_mem)(struct address_space *, pgoff_t, int,
    						void **, unsigned long *);
    	/* migrate the contents of a page to the specified target */
    	int (*migratepage) (struct address_space *,
    			struct page *, struct page *);
    	int (*launder_page) (struct page *);
    	int (*is_partially_uptodate) (struct page *, read_descriptor_t *,
    					unsigned long);
    };
    

    通常,i_fop(inode的指向文件操作函数集的指针)并不直接与块设备联系,而是间接通过a_ops(address_space的页缓冲区操作函数集)读写文件。文件的页缓冲就是i_fop与a_ops之间的缓冲,它是块设备缓冲之上的更高一级缓冲,直接用于具体文件的读写。

     

    Linux的Proc文件系统

    从原理上来讲,计算机中凡是能够提供信息和接受信息的设备或者主体,都可以被抽象成文件。计算机应用程序经常需要了解Linux内核和正在运行进程的当前状态和信息,并且希望能对这些信息做简单的修改。为此,Linux创建了一个专门提供上述信息的文件系统——Proc文件系统,该文件系统具有固定的安装点/proc,所以有时也把它叫做/proc文件系统。

    Proc是一种特殊的文件系统。说它特殊,是因为它的文件并不像普通文件那样存放在外存储器中,它只是存在于内存中的一种文件。同样,在外存储器中也不存在这个文件系统的目录和节点,它们也只存在于内存。当系统关闭之后,Proc文件系统包括其中所有的文件也就不复存在了。

    实质上,Proc文件就是一个特殊的内存区,只不过系统把这个内存区看成文件,并且按照文件方式进行管理。这个文件中存放的都是实时从操作系统的各个部分收集来的动态数据,进程通过访问这个文件不但可以方便地获得内核当前的运行状况和内部数据信息,并且还可以对其进行修改和配置。下面是使用Proc文件系统的优点:

    • 可以利用Proc文件系统的文件,开发一些专门用于获取内核数据的应用程序;
    • 完成用户空间和内核空间的通信,能得到内核运行时的数据,安全且方便;
    • 利用Proc文件可使进程直接对内核的参数进行配置的特点,可以在不重新编译内核的情况下优化系统配置。

    参考文章:深入理解linux系统下proc文件系统内容

     

    展开全文
  • Linux虚拟文件系统全面剖析——打开、读、写逻辑v0.1Linux虚拟文件系统全面剖析——打开、读、写逻辑v0.1Linux虚拟文件系统全面剖析——打开、读、写逻辑v0.1Linux虚拟文件系统全面剖析——打开、读、写逻辑v0.1...
  • 模拟文件系统的c语言实现,操作系统课程设计必备 模拟文件系统的c语言实现,操作系统课程设计必备
  • 5 虚拟文件系统(实现的比较简单)(含代码和makefile) 说明:本程序是简单虚拟文件系统(Windows下也可运行)特点如下: 1.支持10M文件 2.支持多级目录,目录层次无限制(目录和文件总数量好像在1000左右,可自己...
  • vfsStream 是一个用于对真实文件系统进行测试模拟虚拟文件系统的流包装。它能用于任何单元测试框架,例如 PHPUnit 和 SimpleTest。 标签:vfsStream
  • 操作系统课程设计,一个模拟文件系统的实现,可以读文件,写文件,创建文件,删除文件等,设计了inode节点。
  • vfsStream是虚拟文件系统的流包装器,在模拟真实文件系统的单元测试中可能会有所帮助。 它可以与任何单元测试框架一起使用,例如PHPUnit或SimpleTest。 文献资料 参见。 另外,您可能需要检查。
  • Linux 虚拟文件系统(一)概述

    千次阅读 2017-04-16 21:04:26
    Linux (虚拟)文件系统tags: Linux源码Linux 虚拟文件系统 文章梗概 正文 文件系统 虚拟文件系统架构 虚拟文件系统如何知道可用的文件系统有哪些的 不太喜欢的环节 引用 文章梗概本文首先以“尽量不涉及源代码”的...
  • 模拟文件系统实现

    2013-03-17 10:36:12
    **本模拟系统命令列表 login: 登录系统 如:login create: 创建文件 如:create 文件名 delete: 删除文件 如:delete 文件名 read: 读出文件 如:read 文件名 write: 写入文件 如:write 文件名 open: 打开文件 如:open ...
  • 模拟文件系统(Java版)

    热门讨论 2013-01-21 19:41:20
    一个用Java实现的一个虚拟文件系统,支持多用户使用,模拟了数据分块,实现了一些基本的文件目录操作,如创建目录,目录跳转,目录的重命名,复制拷贝,删除,以及文件的创建,编辑,重命名和删除,查看目录和文件的...
  • c++ 实现虚拟文件系统

    2009-01-02 16:31:34
    用c++来实现一个简单的虚拟文件系统 可以实现 多种基本的文件功能
  • 模拟文件系统的设计与实现 本次实验要求学生编程模拟实现操作系统的文件管理系统的如下基本功能: 1、实现文件的创建、查询、删除、修改、更名、拷贝等基本功能; 2、文件系统采用多级目录机制,实现目录的创建、...
  • Linux的虚拟文件系统.pdf

    热门讨论 2012-09-04 13:01:02
    Linux的虚拟文件系统.pdf 很详细的 比书还牛

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,036,757
精华内容 414,702
关键字:

模拟文件系统