linux 文件系统之VFS
简介
基本概念
VFS
VFS(Vritual Filesystem) 是给用户空间程序提供统一的文件和文件系统访问接口的内核子系统。借助 VFS,即使文件系统的类型不同(比如 NTFS 和 ext3),也可以实现文件系统之间交互(移动、复制文件等)
- 从用户空间程序的角度来看,VFS 提供了一个统一的抽象、接口。这使得用户空间程序可以对不同类型的文件系统发起统一的系统调用,而不需要关心底层的文件系统类型。
- 从文件系统的角度来看,VFS 提供了一个基于 Unix-style 文件系统的通用文件模型(common file model),可以用来表示任何类型文件系统的通用特性和操作。底层文件系统提供 VFS 规定的接口和数据结构,从而实现对 linux 的支持。
VFS 的通用数据模型主要包括 4 种对象类型:
- Superblock: 存储了挂载的文件系统的元信息,对于基于磁盘的文件系统,通常在磁盘上有一个对应的 superblock.
- Inode: 一个文件对应一个 inode,每个 inode 都有一个 inode number 唯一标识。inode 通常
- Dentry: 用于将 inode(表示文件)和目录项(表示文件路径)关联起来。inode 中是没有文件路径的,所以需要 dentry 来讲文件路径和文件关联起来。不同的磁盘文件系统使用各自的方式来存储 dentry。路径上的每一个单独的组件,都是一个 dentry。VFS 中没有目录对象,目录只是一种文件。
- File: 用于存储进程和打开的文件之间交互的信息,这个信息只会存在于内核空间中,在磁盘上没有对应的信息。
Superblock
inode
根目录的 inode 号为 0,
|
|
dentry
dentry 是 directory entry 的简称,dentry 是路径上具体的一个组件,一个路径上的每一个组件都是一个 dentry,如路径/bin/vi.txt 中,共有 3 个 dentry,分别是 /, bin, vi.txt。
|
|
dentry 分为三种状态:
- used: 该 dentry 对应一个有效的 inode(dentry 的 d_inode 域指向一个有效的 inode),并且 d_count 是正数,即有一个或者多个用户正在使用该 dentry
- unused: 该 dentry 对应一个有效的 inode(dentry 的 d_inode 域指向一个有效的 inode),并且 d_count 为 0,即 VFS 并没有使用该 dentry,因为该 dentry 仍然指向一个有效的 inode 对象,dentry 当前被保存在 dentry cache 中(等待可能再次被使用)
- negtive: 该 dentry 没有对应一个有效的 inode(dentry 的 d_inode 为 NULL),这种情况可能是因为对应的 inode 对象被销毁了或者是查找的路径名称不对。此时 dentry 仍然被保存在 cache 中,这样下次路径查找可以快速进行(直接从 dentry cache 中获得)
Dentry Cache
dentry cache 的机制由三个部分组成
- used dentry 双向链表:每个 inode 对象都有一个 i_dentry 域,这是一个双向链表,用于保存该 inode 对应的 dentry 对象(一个 inode 可以有很多个 dentry 对象)
- least recently used 双向链表:存储 unused 和 negative 状态的 dentry 对象。该链表按照 lru 的顺序存储,尾部的是最 not lru 的对象,当需要删除 dentry 来释放空间时,从链表的尾部删除对象。
- 哈希表和哈希函数:哈希表存储路径和 dentry 的映射关系,哈希表使用 dentry_hanshtable 数组来存储,数组中每个元素都指向一个由哈希值相同的 dentry 组成的链表。哈希函数根据路径计算哈希值。具体的哈希计算方法由 detry 的操作函数 d_hash()来决定,文件系统可以自己实现这个函数。
dentry 存储在 cache 中时,dentry 的存在导致对应的 inode 的使用计数大于 0,这样 dentry 对象可以将 inode 钉在内存中,只要 dentry 被 cache 了,那么对应的 inode 就一定也被 cache 了(使用的是 inode cache,即 icache),所以当路径查找函数在 dentry cache 中命中时,其对应的 inode 一定也在内存中。
|
|
File
|
|