LInux中的文件系统1
2017-03-08 10:37:55
一、虚拟文件系统VFS
文件系统用于将位于磁盘上的文件按照某种方式组织进内存,并给上层应用程序提供统一的访问接口。Linux支持多种文件系统EXT2/3,NTFS,XFS等,而LInux下支持这些文件系统的方式就是VFS,即虚拟文件系统。虚拟文件系统向上层提供统一的调用接口,向下层请求具体的文件系统。整理架构如图所示。
如上图所描述的,应用程序通过C语言库函数,请求对文件的访问。库函数会调用系统提供的系统调用进入内核,而这里的系统调用不过是一般函数的封装,具体还是要调用VFS提供的调用接口。
虚拟文件系统之所以成为虚拟,源自于其本身并不参与实质性的工作,而是仅仅定义了一组调用接口,像是一个规范一样。这组接口涵盖了几乎所有的文件操作。具体的文件系统不必实现VFS定义的所有操作,只需要根据自己的功能选择性的实现某些操作。
二、虚拟文件系统涉及到的数据结构
一个文件要被访问,自然需要一些数据描述文件的属性,这些信息保存在inode节点中。inode节点主要包含三个部分:文件元数据即访问时间、上次访问日期、引用计数等,具体文件数据和inode操作函数表。从另一个角度,inode其实是磁盘文件在内核中的抽象。对于已经打开的文件,如何恰当的组织才能用最短的时间找到指定文件的inode?Linux通过dentry结构实现这一目的。
1、inode
根据不同文件系统的类型,inode 的实现方式也不同,有些文件系统起初把inode保存在磁盘,后期直接调入到内存如EXT2文件系统;而有些文件系统的inode是在加载文件时动态生成的,如FAT文件系统。VFS中每个文件都有其对应的inode,且只有一个(记住linux依然遵循一切皆文件的道理),所以在inode结构中有很多表示设备文件的字段。在inode中字段记录其引用计数,直到计数值为0时才会被删除,硬链接就是一个很好的例子。inode中包含文件在内存中的映射信息,具体映射由adress_space结构描述。
内存中的inode通过三条链表组织起来,根据inode的状态,分为有效但非活动的inode、使用中但未改变的inode、脏的inode(对应的内容内修改过但是未写入到磁盘)。前面两种保存在全局链表inode_unused、inode_inuse链表中。脏的inode保存在一个特定的超级块的链表中。为了快速查找某个inode,inode还存在于一个散列表中,该散列表是全局表inode_hashtable,散列表的key通过inode编号和超级块地址计算,具体的hash函数在inode的操作函数表中。
2、dentry
dentry 在书上的名称为目录项缓存,其中保存有文件的名称,其本质目的是在具体文件系统路径和inode之间建立一个通道。初次打开一个文件,需要通过底层文件系统和设备驱动和外设交互,没此VFS向底层文件系统发送一个请求,就创建一个dentry保存请求的结果在,这样在下次访问同一个对象时,就不需要访问底层文件系统,直接通过dentry就可以定位具体inode。dentry对象在内存中的组织主要由两种方式:
a) 一个散列表,包含所有的dentry对象。
b) 一个LRU(最近最少使用链表),不在使用的对象不会立即删除,而是设置一个期限,超时后再执行删除。
散列表的哈希函数在dentry对应的操作函数表中,而LRU的表头是全局变量dentry_unused,通过dentry结构中的d_lru连接起来。dentry对象有个计数器d_count,当该计数器到达0时会被置于该链表上,注意,新的向插入链表头,即越往后的dentry,时间就越久,越容易被删除。
2、superblock
该结构式文件系统相关的,每次安装一个文件系统,会有一个对应的超级块结构,当然卸载时,该结构会被删除。每个装载的文件系统对应一个vfsmount结构,用以描述文件系统的装载信息,如装载点的父目录系统、当前文件系统根目录的dentry,还会有指向超级块结构的指针等。
三、进程结构中的文件系统选项
文件系统的存在,无非是让用户去访问文件,而用户如何去发起操作呢?自然是通过进程。各种操作系统的进程访问文件的模式都大同小异,都是先打开进程,然后操作进程。打开进程获取一个局部的文件描述符,windows称之为句柄,该文件描述符只在当前进程内有效。在进程结构task_struct中保存有几个文件系统相关的信息。这里我们只介绍fs_struct和files_struct,对于nsproxy这种命名空间相关,本节不做介绍。
a) files_struct
该结构在进程和打开的文件之间建立连接。在该结构中有个fd_array,是file类型的指针数组,前面提到的文件描述符,其实是该数组的下标。每打开一个文件,就通过数组项纪录在该进程中。而file结构是对应于一个打开的文件,这是相对于进程的,即不同进程打开同一个文件,会有不同的file结构。其中有个比较重要的字段就是f_pos,纪录当前文件偏移,对于读写操作非常重要。还有一个结构f_path,是一个path类型,包含两个指针,分别指向当前文件所述的文件系统结构vfsmount,和文件的目录项结构dentry,通过dentry可以定位具体的inode。而同一文件系统打开的所有文件会通过链表组织起来。
b)fs_struct
该结构记录关于进程本身的一些信息,如当前工作目录的dentry,root的dentry,root文件系统的vfsmount,当前目录的vfsmount等。
下文将结合具体的数据结构内容对各个结构之间的关系进行分析http://www.cnblogs.com/ck1020/p/6544719.html
参考资料:
1、深入Linux内核架构
2、Linux3.10.1内核源码