4. 虚拟文件系统

4. 虚拟文件系统

  • 虚拟文件系统的思想是在不同种类的文件系统和Linux内核之间建立一个虚拟文件系统层,通过调用虚拟文件系统中的读、写或其他函数时,内核都能把它们替换成支持 Linux 文件系统、 NFS 文件系统,或者其他文件系统的实际函数。

1. 虚拟文件系统的作用

  • 虚拟文件系统(Virtual Filesystem),实际上是对各种文件系统的一种封装,为各种文件系统提供了一个通用的接口。通常情况下,为了实现在不同文件系统中实现文件复制(例如,复制/usr/local/arm目录下的 zImage 文件到/mnt/hgfs/Windows目录下),只需要在命令行执行cp /usr/local/arm/zImage /mnt/hgfs/Windows/ 命令,其原理如下图所示:

    image-20240226230829190

  • VFS 支持的文件系统可分为以下 3 个主要类型:

    1. 磁盘文件系统
      • Linux 使用的 EXT2、EXT3及Teiser文件系统
      • UNIX 家族文件系统,如 sysv 文件系统(System V、 Coherent、 Xenix)、 UFS(BSD、Solaris、 NEXTSTEP), MINIX 文件系统及VERITAS VxFS(SCO UnixWare)。
      • Windows 支持的文件系统,如 MS-DOS、FAT、 FAT32、 NTFS 等文件系统。
      • ISO9660CD-ROM 文件系统和通用磁盘的 DVD 文件系统。
      • 其他文件系统,如 HPFS(IBM 公司的 OS/2) 、 HFS(苹果公司的 Macintosh) 、AFFS(Amiga 公司的快速文件系统)及 ADFS(Acorn 公司的磁盘文件系统)。
    2. 网络文件系统( NFS)
      • 网络文件系统最主要的功能就是让网络上的主机可以共享目录及资料。将远端所共享出来的系统,挂载( mount)在本地端的系统上,然后就可以很方便地使用远端的资料,而操作起来就像在本地操作一样。使用 NFS 有相当多的好处,例如文档可以集中管理、节省磁盘空间、资源共享等。
    3. 特殊文件系统
      • 特殊文件系统可以为系统程序员和管理员提供一种容易的方式,来操作内核的数据结构并实现操作系统的特殊特征。

2. 文件系统的注册

  • 每个注册的文件系统是指可能会被挂载到目录树中的各个实际文件系统。实际文件系统,是指 VFS 中的实际操作最终要通过它们来完成而已,并不表示它们必须要存在于特定的某种存储设备上。

  • 注册过程实际上是将表示各实际文件系统的 struct file_system_type 数据结构实例化,接着形成一个链表,内核中用一个名为 file_systems 的全局变量来指向该链表的表头。下面为 file_system_type 数据结构:

    struct file_system_type {
        const char *name;	//文件系统名,如 ext2
        int fs_flags;		//文件系统类型标志
        /* 读超级块的方法 */
        int (*get_sb) (struct file_system_type *, \
                       int, const char *, void *, struct vfsmount *);
        void (*kill_sb) (struct super_block *);	//删除超级块的方法
        struct module *owner;			//指向实现文件模块的文件指针
        struct file_system_type * next;	//指向文件系统类型链表中下一个文件系统的指针
        struct list_head fs_supers;		//具有相同文件系统类型的超级块对象链表的头
        struct lock_class_key s_lock_key;
        struct lock_class_key s_umount_key;
    };
    

3. 文件系统的安装和卸载

  • 在 Linux 系统中,同一个文件系统可以被多次安装,并通过这多个安装点来访问文件系统。但不论文件系统被安装了多少次,文件系统却只有一个,都只有一个超级块对象。安装一个文件系统遵循的步骤:

    1. VFS 首先应找到准备安装的文件系统。查找的方式是,通过查找 file_systems 指针指向的链表中的 file_system_type 数据结构项,来搜索已知的文件系统(该结构中包含文件系统的名字和指向 VFS 超级块读取程序地址的指针),当找到一个匹配的名字时,就可以得到读取文件系统超级块的程序(getsb())地址。
    2. 查找作为新文件系统安装点的 VFS 索引结点,并且同一目录下只能安装一个文件系统; VFS 安装程序必须分配一个 VFS 超级块(super_block),并且向它传递一些有关文件系统安装的信息。
    3. 申请一个 vfsmount 数据结构(其中包括存储文件系统的块设备的设备号、文件系统安装的目录和一个指向文件系统的 VFS 超级块的指针),并使它的指针指向所分配的VFS 超级块。
    4. 当文件系统安装以后,该文件系统的根索引结点就一直保存在 VFS 索引结点缓存中。
  • 卸载文件系统

    • 验证被卸载文件系统是否为可卸载的:
      1. 如果文件系统中的文件或目录正在使用,则 VFS 索引结点高速缓存中可能包含对应的 VFS 索引结点,如果相应的结点标志为“被修改过”,则该文件系统不能被卸载。
      2. 如果验证被卸文件系统为可卸载的,就释放相应的 VFS 超级块和安装点,从而卸载该文件系统。
  • vfsmount 数据结构如下:

    struct vfsmount
    {
        struct list_head mnt_hash;		/* 用于散列表链表的指针 */
        struct vfsmount *mnt_parent; 	/* 指向父文件系统,这个文件系统安装在其上 */
        struct dentry *mnt_mountpoint; 	/* 指向这个文件系统安装点目录的 dentry */
        struct dentry *mnt_root; 		/* 指向这个文件系统根目录的 dentry */
        struct super_block *mnt_sb; 	/* 指向这个文件系统的超级块对象 */
        struct list_head mnt_mounts;	/* 包含所有文件系统描述符的链表头 */
        struct list_head mnt_child; 	/* 用于已安装文件系统 mnt_mounts 的指针 */
        atomic_t mnt_count;				/* 引用计数器,增加该值禁止文件系统被卸载 */
        int mnt_flags;					/* 安装标志 */
        int mnt_expiry_mark; 			/* 如果文件系统到期就设置该标志为 true */
        char *mnt_devname; 				/* 设备文件名,例如/dev/dsk/hda1 */
        struct list_head mnt_list;		/* 已安装文件描述符的 namespace 链表的指针 */
        struct list_head mnt_fslink;	/* 具体文件系统到期链表的指针 */
        struct namespace *mnt_namespace; /* 指向安装了文件系统的 namespace 链表的指针 */
    };
    

ruct namespace mnt_namespace; / 指向安装了文件系统的 namespace 链表的指针 */
};
```

  • 25
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
目录 1 虚拟文件系统概述 5 1.1 通用文件模型 7 1.2 VFS所处理的系统调用 9 2 虚拟文件系统架构 11 2.1 VFS对象数据结构 11 2.1.1 超级块对象 11 2.1.2 索引节点对象 15 2.1.3 文件对象 18 2.1.4 目录项对象 22 2.2 把Linux中的VFS对象串联起来 24 2.2.1 与进程相关的文件 25 2.2.2 索引节点高速缓存 29 2.2.3 目录项高速缓存 30 2.2.4 VFS对象的具体实现 32 2.3 文件系统的注册与安装 38 2.3.1 文件系统类型注册 38 2.3.2 文件系统安装数据结构 41 2.3.3 安装普通文件系统 52 2.3.4 分配超级块对象 58 2.3.5 安装根文件系统 60 2.3.6 卸载文件系统 65 2.4 路径名的查找 66 2.4.1 查找路径名的一般流程 67 2.4.2 父路径名查找 82 2.4.3 符号链接的查找 84 2.5 VFS系统调用的实现 88 2.5.1 open()系统调用 88 2.5.2 read()和write()系统调用 96 2.5.3 close()系统调用 97 3 第二扩展文件系统 99 3.1 Ext2磁盘数据结构 101 3.1.1 磁盘超级块 102 3.1.2 组描述符和位图 105 3.1.3 磁盘索引节点表 105 3.2 VFS接口数据结构 110 3.2.1 Ext2 超级块对象 110 3.2.2 Ext2 的索引节点对象 121 3.2.3 创建Ext2文件系统 124 3.2.4 Ext2的方法总结 126 3.3 Ext2索引节点分配 129 3.3.1 创建索引节点 130 3.3.2 删除索引节点 143 3.4 Ext2数据块分配 144 3.4.1 数据块寻址 145 3.4.2 文件的洞 147 3.4.3 分配数据块 148 4 页面高速缓存 160 4.1 页高速缓存数据结构 160 4.1.1 address_space对象 161 4.1.2 基树 164 4.2 高速缓存底层处理函数 166 4.2.1 查找页 166 4.2.2 增加页 168 4.2.3 删除页 173 4.3 文件系统与高速缓存 175 4.3.1 缓冲头数据结构 175 4.3.2 分配块设备缓冲区页 178 4.3.3 释放块设备缓冲区页 184 4.4 在页高速缓存中搜索块 185 4.4.1 __find_get_block()函数 185 4.4.2 __getblk()函数 188 4.4.3 __bread()函数 190 4.5 把脏页写入磁盘 191 4.5.1 pdflush内核线程 192 4.5.2 搜索要刷新的脏页 193 4.5.3 回写陈旧的脏页 196 5 文件读写 199 5.1 系统调用VFS层的处理 200 5.2 第二扩展文件系统Ext2层的处理 201 5.2.1 Ext2的磁盘布局 202 5.2.2 Ext2的超级块对象 206 5.2.3 Ext2索引节点对象的创建 210 5.2.4 Ext2索引节点对象的读取 218 5.2.5 Ext2层读文件入口函数 225 5.3 页高速缓存层的处理 237 5.3.1 创建一个bio请求 238 5.3.2 得到文件的逻辑块号 244 5.3.3 普通文件的readpage方法 251 5.3.4 块设备文件的readpage方法 252 5.3.5 文件的预读 260 5.4 通用块层的处理 264 5.4.1 块设备的基础知识 265 5.4.2 通用块层相关数据结构 269 5.4.3 提交I/O传输请求 271 5.4.4 请求队列描述符 273 5.5 块设备I/O调度层的处理 281 5.5.1 块设备的初始化 284 5.5.2 建立块设备驱动环境 288 5.5.3 关联block_device结构 295 5.5.4 为设备建立请求队列 306 5.5.5 块设备I/O调度程序 311 5.5.6 真实的I/O调度层处理 321 5.6 块设备驱动层的处理 330 5.6.1 scsi总线驱动的初始化 330 5.6.2 scsi设备驱动体系架构 342 5.6.3 scsi块设备驱动层处理 347 5.6.4 scsi命令的执行 369 5.6.5 scsi命令的第一次转变 372 5.6.6 scsi命令的第二次转变 380 5.7 写文件 384 5.7.1 generic file_write函数 384 5.7.2 普通文件的prepare_write方法 386 5.7.3 块设备文件的prepare_write方法 387 5.7.4 将脏页写到磁盘 388 6 直接I/O与异步I/O 391 6.1 直接I/O 391 6.2 异步I/O 393 6.2.1 Linux 2.6中的异步I/O 394 6.2.2 异步I/O环境 394 6.2.3 提交异步I/O操作 395

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leon_George

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值