linux的文件系统架构

晨曦之光 发布于 2012/04/10 14:59
阅读 603
收藏 0

linux的文件系统是由若干个树形以及链表的结构组成的,其中众所周知,所有的目录和文件组成了视觉上“一棵”树,在这“一棵”树背后有一条挂载链表,如果说每一个文件系统都是一棵树的话(实际上就是如此),这个链表将很多棵树链接成了那“一棵”树,因此,linux的文件系统是由很多棵树组成的,这些树通过挂载链表联系在了一起,比如/tmp/my是一个目录,下面有文件file1,而我们可以将一个磁盘分区D挂载在这个目录下,此时/tmp下面的文件就是磁盘分区D下面的文件了,不仅仅如此,通过这个模型还可以实现非存储性质的文件系统甚至任意的文件系统,比如procfs,sysfs,tmpfs等等,在已挂载的文件系统的任意目录挂载任意的文件系统,这些文件系统可以在磁盘上,可以在网络上,可以在内存中,也可以在你心里,由此看来,这种文件系统实际上是可以无限扩展的。
     在最底层,linux维护了一个磁盘inode的概念,它代表了一个实际文件,然后在上一层,linux维护了内存inode,它使得操作系统可以提供用户接口来操作磁盘inode,内存inode和磁盘inode是对应的,vfs层将不同文件系统的不同格式的磁盘inode统一成了一致的内存inode,如此一来向上提供的接口将统一,在接口统一之前,数据结构首先要统一。和内存inode相关的是目录项dentry的概念,它绑定一个且只绑定一个内存inode,但是却允许多个dentry绑定同一个内存inode,实际上它就是我们在使用操作系统时看到的每一个文件的内核实体,既然允许dentry和inode的多对一的关系,操作系统很简单地就可以实现诸如链接这样的概念,这个意义上dentry并不是和内存inode处于同一个层次,inode表示文件的本质,而dentry表示操作系统意义上文件的接口。
     unix最先实现了vfs,在unix中内存inode成为vnode,这个名称可能更好听些。这个vfs在linux中的实现要更复杂一些,其本质就是这个内存inode数据结构,进而在该数据结构的基础上提供file_operations操作函数集,这些数据结构是怎样组合起来的呢?它们是在什么时候组合在一起的呢?任何事情如果想搞透它就要从起源开始研究,于是sys_open系统调用中必然将这一切联系在了一个,如果说sys_open还不够的话,那么sys_mount作为一个文件系统的开始一定确定了该文件系统的基本模板,比如super_block结构之类的,由于sys_mount还是要使用sys_open,那么sys_open当然是重中之重了。open的轮廓为两层循环,外部的循环解析路径,内层的循环在特定的路径寻找待open路径中下一个元素,路径元素由'/'分割。在进一步处理下一个路径元素之前,必须将当前的dentry设置到当前目录的最顶一层挂载的文件系统的根目录,这个在linux中由follow_mount来实现,这样所有被mount的目录下的原始内容就被隐藏了,原先的树依然存在,只是在这个节点上又长出一个新的根,然后这个新根又扩展成一棵树,任意的树节点上都可以生长出新根,然后递归地长出新树。
     系统中每一个被挂载的文件系统都有一个超级块,超级块是该文件系统的元数据 ,所有的同类文件系统的超级块链接成一个链表,在超级块回调函数的指导之下,系统模块可以支持各种各样的文件系统。系统中还有一张挂载表,实际上是挂载树,很多内核实体都是同时连入不同的数据结构,这样就方便在不同场合使用不同的数据结构,比如vm_area_struct既连入链表,又连入红黒树中。这个挂载表的每一项表示一次挂载,包含一个挂载文件系统的超级块信息,被挂载点的inode对应的dentry,挂载文件系统根的inode对应的dentry以及设备号。
     每个挂载的文件系统都有一个根,即“/”,它是一个特殊的目录,一般每一类文件系统都会为这个根分配一个固定的内存inode号,然后为后续此挂载文件系统分配挂载范围内唯一的inode号,因此不同挂载点的文件系统中的文件的内存inode号会相同,注意,一般不要提及磁盘inode号是否唯一的问题和概念,因为并不是每一种文件系统都有磁盘inode概念的,unix/linux只是为了实现vfs才将很多的文件系统统一“适配”到内存inode(vnode),比如ntfs就没有inode的概念,当在linux上挂载ntfs分区的时候,内核的ntfs模块会将ntfs文件的元数据装载到内存inode中,这就是适配器模式在linux内核的应用。


原文链接:http://blog.csdn.net/dog250/article/details/5822427
加载中
返回顶部
顶部