VFS之基本数据结构
来源:互联网 发布:网络摄像头忘记密码 编辑:程序博客网 时间:2024/06/05 00:26
文件系统是一种存储和组织计算机中文件数据的一系列抽象数据类型,它们用来实现数据的存储、管理、查看、等功能。在Linux系统中,所有的设备、进程都是以文件的形式存在,字符设备、块设备以及这些设备的驱动均要依靠文件系统来实现,设备管理的基础框架也要以来文件系统(sysfs),所以文件系统在Linux操作系统中担任着重大的作用。
一、VFS介绍
Linux内核通过虚拟文件系统(Virtual File System,VFS)管理文件系统。VFS对所有的文件系统(如Ext3、Ext2等)提供了一个统一的接口,它在Linux文件系统中担任着及其重要的角色,是一个不可或缺的基础设施;在文件系统的访问操作中,必须通过虚拟文件系统提供的接口才能实现正常的文件操作。同时,在Linux操作系统中,对于所有的文件系统都要遵循虚拟文件系统VFS定义的方式实现。
VFS与具体文件系统的关系
VFS支持三种类型的文件系统:基于磁盘的文件系统、特殊的文件系统和网络文件系统。
基于磁盘的文件系统:管理在非易事戒指上存储的文件。这种类型的文件系统最多,比如常见的ext2/3/4、fat、ntfs等。
特殊的文件系统:在内核中生成,是一种使用户应用程序与用户通信的方法,比如常见的proc文件系统,它存储于内存,不占用硬件存储空间。
网络文件系统:这种文件系统可以通过网络访问另一台计算机上的数据,相当于连接到本地计算机一样。比如nfs文件系统。
二、VFS基本数据结构
VFS通用文件模型包含有4种基本的数据结构,通过这几个数据结构实现将硬盘上的文件抽象到内存中:
超级块
目录项
索引节点
文件
这四个数据结构的关系如图所示:
2.1. 超级块(super-block)
超级块代表了整个文件系统本身。Super_block保存了Linux文件系统设定的操作函数还有文件块的大小等信息;super_block是文件系统自己的控制块结构,它的链表头链接来文件系统中的所有inode。由于控制块对于一个具体的文件系统来说,有可能还包含其它的信息;想要找到这些信息,我们就可以通过超级块super_block对象进行查找。
由于超级块super_block是具体物理文件系统super_block超级块在内存的抽象,因而需要物理文件系统的超级块来获取超级快的内容。
super_operations 提供了最重要的超级块操作。例如super_operation 的成员函数read_inode提供了读取inode 信息的功能。VFS虚拟文件系统提供了文件系统的架构,具体的物理文件系统就要遵循这个定义好的架构来实现。Super_operations函数是每个文件系统都要提供的一个函数,因为要通过它来获取inode的信息。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
2.2. inode节点
inode代表一个文件。Inode记录了文件的基本信息,包括文件创建时间、大小、使用者、块大小等参数,以及对文件的读写缓存和读写函数等信息。由于考虑到文件系统中存在文件的链接,所以说一个物理文件系统可能会有多个目录项dentry,指向多个文件的路径;而inode就只有一个。
索引节点inode的数据结构非常庞大,下边介绍介个比较重要的结构成员。inode的结构定义如下:
inode的代码数据结构
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
成员i_list、i_sb_list、i_dentry分别是三个链表头。i_sb_list成员用于链接到super_block中的inode链表;i_list成员用于连接描述索引节点当前状态的链表。在对一个inode进行操作时,为了表示inode处于使用状态,i_list成员需要连接到inode_in_use链表;同时文件系统的super_block的s_inodes链表头也要被i_sb_list成员链接。
成员i_ino是inode的号,而i_count是inode的引用计数。成员i_size是以字节为单位的文件长度。
成员i_blkbits是文件块的位数。
成员i_fop是一个struct file_operations类型的指针。这个结构提供了文件的异步输入输出函数和读写函数;每个文件系统,对于文件的操作都有属于自己的函数。
i_mapping是一个重要的成员。这个结构主要提供了缓存文件内容的功能在对文件进行读写操作时,首先在i_mapping成员包含的缓存中寻找文件内容,缓存中如果有,就直接获取,可以大大的提高文件的读操作效率,否则的话就需要去物理磁盘读取文件内容。同样,写操作也是如此,先写入至缓存文件,然后再写入磁盘。
成员i_bdev是指向块设备的指针。文件所在文件系统绑定的块设备就是成员i_bdev指向的块设备。
2.3. dentry目录项
dentry的中文名是目录项,它是Linux中索引节点的链接。直观一点来看,大多数的文件系统都是以树状结构存储;目录递归存储,一层一层的,从树根目录开始,直到目录的最底层文件;而在Linux系统中dentry就反应了文件系统中目录和文件的树状关系。
在Linux系统中所有的东西都是以文件的形式存在,同样在虚拟文件系统中,目录也相当于一个文件。根目录有一个目录项结构,并且每一个文件也都至少有一个目录项,一层一层递归,下级目录或文件链接到上级目录的dentry,二级目录、三级目录同样如此,从而形成一个树状结构,并且可以通过根目录项遍历所有的文件和目录。
在Linux中有一个称为dentry cache的东西,是内核使用哈希表对dentry进行缓存,以便加快系统对dentry的查找。由于目录项的查找经常都是先在dentry cache中进行的,所以dentry cache在文件的操作中是经常会被用到的。
dentry目录项和super_block的结构定义类似,很复杂,下边会列出一些比较重要的部分。简化后的dentry结构定义如下:
dentry架构的简化定义
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
对dentry结构的成员解释如下。
d_inode指向一个inode结构。这个inode和dentry共同描述了一个普通文件或者目录文件。
d_subdirs成员和d_child成员。d_subdirs是子目录项(其可以是文件也可以是目录)的链表头,dentry结构中的所有子项都要链接到d_subdirs链表。d_child是dentry自身的链表头,需要链接到父dentry的d_subdirs成员。在进行文件的移动操作时,要将目录项结构从当前父目录项的链表上脱离,然后再将其链接至新的父dentry目录上的d_subdirs成员。
d_parent是指针,指向父dentry结构。
d_hash是链接到dentry cache的hash链表。
d_name成员保存的是文件或者目录的名字。在打开文件的时候,根据这个成员和目录的的名字来寻找目标文件。
d_mounted用来指目录项是否是一个挂载点。如果是挂载点,该成员不为零。
2.4. file
描述文件和进程交互的关系就是文件对象的作用。实际上,在硬盘上就不存在一个文件结构。对于同一个文件,在不一样的进程中就有不一样的文件对象;在用户进程打开一个文件时,系统内核就会动态的创建一个对应的文件对象。
文件的数据结构
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
成员f_dentry和f_vfsmnt成员分别指向文件对应的目录项结构和文件所属于的已挂载文件系统。
f_pos成员存储着进程操作文件对象时的位置。比如读取文件的前20个字节内容,f_pos成员就会指向第21个字节位置。
f_uid和f_gid分别表示文件的用户ID和用户组ID。
f_mapping指向一个address_space结构。
三、read系统调用在VFS中的实现
在用户态使用read函数时,内核会根据具体系统调用来选择对应的处理函数(即就是read函数)。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
vfs_read函数根据file对象当前操作指针的位置得到f_op(file_operations结构体)的指针,从而获得file_operations结构体中的read操作函数,对文件进行read操作,将内核读取的文件内容存入char __user* buf指向的内存地址
- VFS之基本数据结构
- VFS之基本数据结构
- VFS中的基本数据结构
- VFS中的基本数据结构
- VFS文件系统之二: VFS的数据结构
- VFS对象数据结构
- linux VFS数据结构(一)
- linux VFS数据结构(二)
- VFS的数据结构
- linux----VFS中的数据结构
- VFS对象数据结构
- vfs的数据结构
- 文件系统VFS数据结构
- Apache VFS:基本介绍
- 数据结构之基本英语
- 基本数据结构之堆栈
- 基本数据结构之队列
- 基本数据结构之队列
- DecimalFormat对数值格式化的舍入问题——RoundingMode
- 数据库事务、并发、锁那些事
- Mybatis中实现oracle的批量插入、更新
- HTTPS认识(二)证书
- firewall-cmd常用语法速记
- VFS之基本数据结构
- 解决Gson 处理Map将整型处理为浮点型的问题
- 使用ffmpeg进行音视频编解码时用到的函数介绍
- mongodb维护常用命令
- 单点登录(九)-----遇到问题-----FileNotFoundException: class path resource-UsernamePasswordWrapperAuthenticatio
- 跟阿铭学Linux-笔记1:初步认识Linux
- Switching Eds: Face swapping with Python, dlib, and OpenCV
- 在service中监控横竖屏的切换
- 【Oracle数据库】层次查询