文件系统是组织文件的一种形式,从而使得应用程序能够更具效率地对文件进行读写。Linux支持很多种文件系统类型,但整体来说它们或多或少有一些共同的元素,比如superblock、data block、metadata block、inode、timestamp等。
对于初学者而言,可以这样理解文件系统:一个文件系统是一个有很多抽屉的柜子,文件就是抽屉里装的东西,其中柜子、抽屉、文件的相关信息可以用superblock、block、inode或者其他名词进行描述,不同文件系统的区别主要体现于这些抽屉与文件的组织方法、柜子内的文件目录索引等。如果是类似Ceph、Gluster的分布式文件系统,我们可以将其理解成多个“柜子”组成的“柜子阵列”,相关细节会在本章第三节进行介绍。
如前所述,文件系统是对文件的组织形式,一个完整的文件系统实现中需要有到inode、superblock等基本元素的操作。为了让读者更好地理解这些内容,笔者从较为简单的simplefs(https://github.com/psankar/simplefs)、aufs(https://github.com/krinkinmu/aufs)和lwnfs(https://gist.github.com/prashants/3496839)中选择只有300行左右的lwnfs作为实例,对文件系统模块所做的工作进行介绍。
首先我们创建目录lwnfs,如下所示编写模块Makefile,其中笔者的操作系统为Fedora 23,内核版本为4.4.5。
然后下载lwnfs.c并修改部分函数与变量以使其能够在Linux 4.4中编译,包括其中的inode结构和d_alloc_root()函数,修改后的文件可以从https://github.com/lofyer/lwnfs获取。通过阅读源码,我们可以看出这个文件系统模块的主要内容包括注册文件系统类型、注册inode操作等。
□注册文件系统类型
首先是模块注册函数,即向VFS注册文件系统。
□实现inode创建操作
不同文件系统的inode操作的实现有所不同,这是它们之间的主要差别之一,如下是lwnfs实现的inode操作。
□注册inode操作(www.xing528.com)
这些操作也就是用户对此文件系统中的文件可以执行的操作,lwnfs只实现了最基本的open()、read()、write()。其中的lfs_read_file()在会将被调用时且读取偏移量为0的情况下,将文件内容加1(数据类型为atomic_t),然后将结果再写入至文件中。
□挂载时初始化superblock
其中涉及的两个主要函数是lfs_get_super()和lfs_fill_super(),前者会获取superblock的dentry,并使用lfs_fill_super对这个super_block进行初始化,初始化包括superblock的大小、标识符、可执行操作等。
□初始化文件系统
在挂载lwnfs后,其中与根目录相关的函数(来自内核libfs库,无需额外实现)会对挂载点内容进行更新,包括创建一个用于计数stats操作的文件“counter”、一个子目录“subdir”以及其中的“subcounter”。
接下来我们对其进行测试,包括挂载以及文件的读写。
由于未定义mkdir()、create()等inode操作,所以就不能进行目录或文件的创建,如下所示。
比如要实现创建目录的功能,我们定义并注册inode操作mkdir(),具体实现可参考其中的lfs_create_file函数以及aufs或者simplefs的实现。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。