4. 虚拟文件系统
- 虚拟文件系统的思想是在不同种类的文件系统和Linux内核之间建立一个虚拟文件系统层,通过调用虚拟文件系统中的读、写或其他函数时,内核都能把它们替换成支持 Linux 文件系统、 NFS 文件系统,或者其他文件系统的实际函数。
1. 虚拟文件系统的作用
-
虚拟文件系统(Virtual Filesystem),实际上是对各种文件系统的一种封装,为各种文件系统提供了一个通用的接口。通常情况下,为了实现在不同文件系统中实现文件复制(例如,复制
/usr/local/arm
目录下的 zImage 文件到/mnt/hgfs/Windows
目录下),只需要在命令行执行cp /usr/local/arm/zImage /mnt/hgfs/Windows/
命令,其原理如下图所示: -
VFS 支持的文件系统可分为以下 3 个主要类型:
- 磁盘文件系统 :
- 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 公司的磁盘文件系统)。
- 网络文件系统( NFS)
- 网络文件系统最主要的功能就是让网络上的主机可以共享目录及资料。将远端所共享出来的系统,挂载( mount)在本地端的系统上,然后就可以很方便地使用远端的资料,而操作起来就像在本地操作一样。使用 NFS 有相当多的好处,例如文档可以集中管理、节省磁盘空间、资源共享等。
- 特殊文件系统
- 特殊文件系统可以为系统程序员和管理员提供一种容易的方式,来操作内核的数据结构并实现操作系统的特殊特征。
- 磁盘文件系统 :
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 系统中,同一个文件系统可以被多次安装,并通过这多个安装点来访问文件系统。但不论文件系统被安装了多少次,文件系统却只有一个,都只有一个超级块对象。安装一个文件系统遵循的步骤:
- VFS 首先应找到准备安装的文件系统。查找的方式是,通过查找
file_systems
指针指向的链表中的file_system_type
数据结构项,来搜索已知的文件系统(该结构中包含文件系统的名字和指向 VFS 超级块读取程序地址的指针),当找到一个匹配的名字时,就可以得到读取文件系统超级块的程序(getsb()
)地址。 - 查找作为新文件系统安装点的 VFS 索引结点,并且同一目录下只能安装一个文件系统; VFS 安装程序必须分配一个 VFS 超级块(super_block),并且向它传递一些有关文件系统安装的信息。
- 申请一个
vfsmount
数据结构(其中包括存储文件系统的块设备的设备号、文件系统安装的目录和一个指向文件系统的 VFS 超级块的指针),并使它的指针指向所分配的VFS 超级块。 - 当文件系统安装以后,该文件系统的根索引结点就一直保存在 VFS 索引结点缓存中。
- VFS 首先应找到准备安装的文件系统。查找的方式是,通过查找
-
卸载文件系统:
- 验证被卸载文件系统是否为可卸载的:
- 如果文件系统中的文件或目录正在使用,则 VFS 索引结点高速缓存中可能包含对应的 VFS 索引结点,如果相应的结点标志为“被修改过”,则该文件系统不能被卸载。
- 如果验证被卸文件系统为可卸载的,就释放相应的 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 链表的指针 */
};
```