VFS

VFS

VFS抽象数据结构

- 超级块(superblock): 存放文件系统控制信息

- 索引节点(inode):    存放具体文件的一般信息,用来标识存储介质上的文件

- 文件(file):         存放已打开的文件和进程之间交互的信息

- 目录项(dentry):     存放文件的名称和文件的路径

其他重要数据结构包括

- file_system_type:  用来描述不同的文件系统

- vfsmount:      描述系统中已经挂载的文件系统信息,用于对超级块和inode进行跟踪

 

superblock的主要数据结构

作用

s_list

指向下一个superblock,所有的superblock组成一个链表,头指针保存在super_blocks变量中

s_fs_info

指向特定文件系统的superblock信息,比如ext2,这个指针指向ext2_sb_info结构

s_dirt

因为superblock既存在于内存中也存在于磁盘中,所以需要这个标记标示内存中的数据是否和磁盘中的同步

s_root

文件系统根目录的dentry,表示这个文件系统的mount点

s_inodes

指向所有inodes组成的链表的头指针

s_files

指向所有file对象组成的链表的头指针

s_op

超级块操作函数集,struct super_operations类型,包括alloc_inode,destroy_inode,put_super等函数,用来管理这个文件系统中的 inode 的函数

 

 

inode的主要数据结构

作用

i_dentry

指向本inode的所有dentry对象组成的链表的头指针

i_ino

指向特定文件系统的superblock信息,比如ext2,这个指针指向ext2_sb_info结构

i_nlink

inode的硬连接引用计数

i_count

进程对inode的引用计数

i_uid/i_gid

所属用户/组的id

i_atime

inode访问时间,类型域有i_mtime和i_ctime

i_mode

inode的权限

i_size

文件大小(单位:字节)

i_data

数据地址索引,struct address_space结构类型

i_mapping

内存索引页面,struct address_space结构类型指针,指向i_data(?)

i_blocks

所占的block数

i_bytes

最后一个block使用了的字节数

i_sb_list

指向super_block中s_inodes链表中本inode的下一个inode

i_op

索引节点操作函数集,inode_operations类型,定义直接在 inode 上执行的操作

i_cdev/i_pipe/i_bdev

非特殊文件时,inode所存储的设备

i_rdev

非特殊文件时,所存储设备的设备号

dentry的主要数据结构

作用

d_name

文件名

d_inode

指向的inode

d_parent

父目录的dentry对象

d_count

目录项对象使用计数器

d_child

对于目录来说,和本dentry相同父目录的目录dentry对象链表的头指针

d_subdirs

对于目录来说,当前dentry下的子目录dentry对象链表的头指

d_alias

指向相同inode的所有dentry对象构成的链表的头指针

d_op

目录项操作表,dentry_operations类型

d_sb

文件的超级块对象

 

 

file的主要数据结构

作用

f_dentry

指向当前file对象关联的dentry对象

f_vfsmnt

 

f_pos

文件指针

f_op

定义与文件和目录相关的方法(即标准系统调用POSIX标准文件I/O管理函数),file_operations结构类型

 

 

file_system_type的主要数据结构

作用

name

文件系统的名称

fs_flags

一些特殊标记,如FS_REQUIRES_DEV

mount

本文件系统的挂载方法,执行kern_mount函数时调用

kill_sb

卸载文件系统超级块的方法

next

file_system_type类型单项链表,指向其他文件系统,单链表的表头由全局变量file_systems表示

fs_supers

双向链表,指向本文件系统所支持的super_block

vfsmount的主要数据结构

作用

mnt_parent

上一层挂载点

mnt_mounts

子文件系统的链表头

mnt_child

指向 上一层挂载点mnt_mounts形成双链表 的兄弟结点

mnt_mountpoint

指向挂载点dentry结构的指针

mnt_root

指向本文件系统的根路径dentry

mnt_sb

指向文件系统超级块

mnt_flags

挂载选项,如MNT_NODEV,MNT_READONLY等

mnt_list

指向vfsmount结构所形成链表的头指针(?)

tip:通常,superblock, inode会保存至存储介质,而dentry ,file仅存在于内存中

inode的管理:Inode-cache hash表inode_hashtable索引节点缓存

dentry的管理:

我们知道,若干dentry描绘了一个树型的目录结构,这就是用户所看到的目录结构,每个dentry指向一个索引节点(inode)结构然而,这些dentry结构并不是常驻内存的,因为整个目录结构可能会非常大,以致于内存根本装不下。Linux的处理方式为:初始状态下,系统中只有代表根目录的dentry和它所指向的inode。当要打开一个文件,文件路径中对应的节点都是不存在的,根目录的dentry无法找到需要的子节点(它现在还没有子节点),这时候就要通过inode->i_op中的lookup方法来寻找需要的inode的子节点,找到以后(此时inode已被载入内存),再创建一个dentry与之关联上。
由这一过程可见,其实是先有inode再有dentry。inode本身是存在于文件系统的存储介质上的,而dentry则是在内存中生成的。dentry的存在加速了对inode的查询。

为了提高目录项对象的处理效率,加速对重复的路径的访问,引入dentry cache(简称dcache),即目录项高速缓。它主要由两个数据结构组成: 
1、哈希链表dentry_hashtable:dcache中的所有dentry对象都通过d_hash指针域链到相应的dentry哈希链表中。 
2、未使用的dentry对象链表dentry_unused:dcache中所有处于unused状态和negative状态的dentry对象都通过其d_lru指针域链入dentry_unused链表(super_block->s_dentry_lru)中。该链表也称为LRU链表。

目录项高速缓存dcache是索引节点缓存icache的主控器(master),即dcache中的dentry对象控制着icache中的inode对象的生命期转换。无论何时,只要一个目录项对象存在于dcache中(非negative状态),则相应的inode就将总是存在,因为inode的引用计数i_count总是大于0。当dcache中的一个dentry被释放时,针对相应inode对象的iput()方法就会被调用。

为了保证内存的充分利用,在内存中生成的dentry将在无人使用时被释放。d_count字段记录了dentry的引用计数,引用为0时,dentry将被释放。
这里的释放dentry并不是直接销毁并回收,而是将dentry放入目录项高速缓的LRU链表中。当队列过大,或系统内存紧缺时,最近最少使用的一些dentry才真正被释放。

现总结如下 
当寻找一个文件路径时,对于其中经历的每一个节点,有三种情况: 
1, 对应的dentry引用计数尚未减为0,它们还在dentry树中,直接使用即可; 
2, 如果对应的dentry不在dentry树中,则试图从LRU队列去寻找。LRU队列中的dentry同时被散列到一个散列表中,以便查找。查找到需要的dentry后,这个dentry被从LRU队列中拿出来,重新添加到dentry树中; 
3, 如果对应的dentry在LRU队列中也找不到,则只好去文件系统的存储介质里面查找inode了。找到以后dentry被创建,并添加以dentry树中。

与vfs紧密相关的内核模块主要是进程 
涉及到四个重要的数据结构: 
    file, fs_struct, files_struct 和 namespace(nsproxy) 
fs_struct     用于表示进程与文件系统之间的结构关系,比如当前的工作目录,进程的根目录等等. 
files_struct  用于表示当前进程打开的文件表 
关于namespace可以去了解nsproxy 
在内核中用file来表示某个被打开的文件,通过在进程结构体(task_struct)中嵌入fs和files来管理文件 
Linux中,常常用文件描述符(file descriptor)来表示一个打开的文件,这个描述符的值往往是一个大于或等于0的整数. 
而这个整数,其实就是在files_struct中file数组fd_array的下标. 
对于所有打开的文件, 这些文件描述符会存储在fd_array的位图中

nameidata是搜索辅助结构体,用于在路径查找过程中记录中间信息和查找结果

下面介绍用户空间与文件系统交互的过程 
当进程通过open等系统调用打开一个文件路径时, 
内核通过nameidata在内核中保存结构体file来建立与该文件对应的dentry 和 inode关联, 
并返回一个标识该file的文件描述符fd,并建立其与(structfiles_struct)task_struct->files之间的关系供进程使用 
然后进程就可以通过操作该fd来对文件进行read write ioctl llseek等操作(vfs_xxx ==> file->f_op==> inode->i_op)

路径查找过程:
do_path_lookup来翻译VFS的路径名
user_path_parent
查找结果存放在一个临时变量nameidata(变量一般都缩写为nd)中 


下图展示了进程和文件之间的关系

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值