内容简介:Linux 的成功有一部分原因在于能够很好的支持不同的文件系统,你能够轻松透明地把 Windows、其他 Unix 系统、甚至是占有极小份额的 Amiga 使用的文件系统VFS 背后的 idea 是在 kernel 中抽象出不同文件系统,针对具体的文件系统,Linux kernel 实现具体的操作方法。当系统调用要执行一个
Linux 的成功有一部分原因在于能够很好的支持不同的文件系统,你能够轻松透明地把 Windows、其他 Unix 系统、甚至是占有极小份额的 Amiga 使用的文件系统 mount
到 Linux 的文件系统中。这是通过 Virtual Filesystem
(以下简称 VFS)实现的。
VFS 背后的 idea 是在 kernel 中抽象出不同文件系统,针对具体的文件系统,Linux kernel 实现具体的操作方法。当系统调用 read
、 write
发生时,kernel 根据操作的具体文件系统,比如 native Linux文件系统、NTFS(Windows NT)等,调用相对应的函数。
实例: cp
要执行一个 cp
指令:
cp /floppy/TEST /tmp/test 复制代码
其中 /floppy
是一个 mount 的MS-DOS文件系统,而 /tmp
是 ext2。 VFS 就是应用程序和底层文件系统实现之间的一个抽象层 , cp
不需要知道 /floppy/TEST
个 /tmp/test
的文件系统类型,它只需要调用标准的系统调用,比如 read
、 write
这些, 把底层文件系统不同带来的复杂度交给 kernel 。
示例的代码如下:
inf = open("/floppy/TEST", O_RDONLY, 0); outf = open("/tmp/test", O_WRONLY|O_CREAT|O_TRUNC, 0600); do { i = read(inf, buf, 4096); write(outf, buf, i); } while (i); close(outf); close(inf); 复制代码
示意图:
代码和截图来源于 《Understanding the Linux Kernel, Third Edition》 P457
VFS 支持的文件系统
VFS 支持嗯文件系统一共分为下面三大类:
- Disk-based FS
本地的 disk。包括:
- ext2, etx3, ext4
- Unix 家族,比如 sysv 文件系统、UFS(BSD,solaris)、MINIX等
- Microsoft 文件系统,比如 MS-DOS、NTFS
- ISO9660 CD-ROM(之前的High Sierra Filesystem)
- 其他冷门
- Network FS
这一类支持访问远程的文件系统,比如 NFS、Coda、AFS 等。
- Special FS
如 /proc
虚拟文件系统。
通常来说,root 目录为 Linux 原生的 ext2
、 ext3
、 ext4
,其他类型的文件系统通过 mount
形式 mount 到某个特定子目录。
Common File Model
VFS 背后的核心idea: 用common file model表示所有现实中的FS。这个模型严格使用原生Unix FS 模型,每个特定的 FS 都需要将自己的硬件结构翻译成 common file model。
比如在 common file model 中,目录也被看做文件,包含其他的文件盒目录。然而,一些非 Unix 的 FS,使用的是 file allocation table(FAT),这种情况下,目录不是文件。但是为了遵循 common file model的规则,Linux 对这种 FAT-based 的 FS,必须能够抽象出一个遵循common file model 的接口。
更加具体点,Linux kernel 在处理 read
、 ioctl
这些系统调用的时候,不能直接硬编码,使用某个特定的底层函数。kernel实际上针对每一个操作,使用的是一个指针,这个指针指向了针对此文件系统专门的处理函数。
让我们来看看kernel 是如何完成上面提到的 cp
操作的。
应用层调用 read()
,kernel 实际上会调用 sys_read()
service routine(其他的系统调用也一样)。MS-DOS FS 的文件被 kernel memory 中的一个数据结构表示,这个数据结构包含一个 f_op
字段,指向的是针对 MS-DOS 的 read 函数。 sys_read()
找到这个函数然后调用它。所以整个过程可以看作是:
read() -> sys_read() -> file data structure -> f_op -> read_for_msdos() 复制代码
调用 write()
也一样,这个系统调用会触发针对 ext2
FS 的写调用。
简要来说, 对于每个 open()创建的 file object,kernel 需要负责正确赋值此 file object的指针,指向针对此文件系统的特定函数,然后调用这些函数。
CFM 包含哪些 object types
- superblock object:包含的是 mounted FS 的数据。
- indoe object:特定文件的数据。对于 disk-based FS,这个 object 一般对应一个 file control block。每个 inode object 都有一个 inode number,唯一指定 FS 中的某一个文件。
- file object:一个open file 和进程之间的交互信息。这个 object 只在进程打开文件的时候在kernel memory 中存在
- dentry object:文件名到inode的映射,不同的 FS 有不同的底层实现。
总结一下
VFS 是应用和特定文件系统之间的一层抽象,有些操作能够直接在 VFS 层完成,不需要涉及到底层的具体文件系统。比如说,当进程close file的时候,disk 上的文件本身是不会改变的,所以 VFS 只要把对应的 file 对象释放掉就行了。再比如说, lseek()
系统调用,改变的也是内存中的 file 对象,而不需要设计底层的文件系统。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Mozilla 20 周年:我们的使命是打造更好的互联网
- Ubuntu 17.10 本月结束使命,用户应升级至 18.04
- Gavin Wood 谈 Polkadot 的「疯狂表亲」Kusama 使命与进展
- Spring Boot 2.1.5 正式发布,1.5.x 即将结束使命!
- 人工智能发展需要真正的开源开放,OpenI启智平台肩负使命正式启航
- 万维网之父新使命:把互联网数据控制权归还给网民
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。