Skip to content

Commit 0b67c51

Browse files
committed
learning vfs pdf
1 parent 4a4496c commit 0b67c51

File tree

1 file changed

+47
-1
lines changed

1 file changed

+47
-1
lines changed

为了工作/Linux/内核层/Linux Virtual Filesystem.md

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ categories:
55
- 内核层
66
abbrlink: f548d964
77
date: 2024-12-24 16:05:00
8-
updated: 2024-12-26 15:50:00
8+
updated: 2024-12-27 17:40:00
99
---
1010

1111
<meta name="referrer" content="no-referrer"/>
@@ -28,6 +28,24 @@ Linux 内核使用 VFS 处理目录和文件的层次结构(其实是一棵树
2828

2929
VFS 的基本思想是提供可以表示任何文件系统文件的单一文件模型。文件系统驱动程序需要遵守公共的基准。这样,内核可以创建包含整个系统的单一目录结构。其中一个文件系统将作为根文件系统,其他文件系统将挂载在其各个目录下。
3030

31+
# 存储栈整体结构
32+
33+
Linux 存储栈的整体结构图如下。从上到下分别是:**VFS、通用块层、SCSI 层、块设备层**
34+
35+
<img src="https://img-blog.csdnimg.cn/direct/e2fa79efbb584048a112f1965d9156d5.png" alt="image-20241227142615377" style="zoom:75%;" />
36+
37+
各个层次的作用如下。
38+
39+
1. VFS:VFS 层是 Linux 最为津津乐道的设计,也就是所谓的一切皆文件。它通过统一的接口,底层封装了各种各样的文件系统。
40+
41+
2. 通用块层:文件系统将读/写请求转换成 bio 和 request,提交给通用块层,通用块层对 request 进行调度,发往下一层。
42+
43+
<img src="https://img-blog.csdnimg.cn/direct/ae3f1960badf4746813099ae4ef7b206.png" alt="image-20241227143348812" style="zoom:80%;" />
44+
45+
3. SCSI 层:SCSI(Small Computer Systems Interface)是一组标准集,定义了与大量设备(主要是与存储相关的设备)通信所需的接口和协议。Linux 提供了一种 SCSI 子系统,用于与这些设备通信。
46+
47+
4. 块设备层:块设备层负责对某种具体的物理设备进行处理,完成相应的读写请求。
48+
3149
# 常见的文件系统模型
3250

3351
任何实现的文件系统都需要包含这几种明确定义的类型:superblock、inode、file 和 dentry。这些也是文件系统的元数据。
@@ -91,6 +109,14 @@ dentry 在磁盘上有对应物,但对应关系不是直接的。每个文件
91109

92110
在 VFS 中,dentry 实体由 `struct dentry` 结构表示,与之相关的操作在 `struct dentry_operations` 结构中定义。
93111

112+
## 其他数据结构
113+
114+
除了上述,VFS 中还有一些数据结构。
115+
116+
1. address_space/mapping:表示一个文件缓存,结构体的名字称为 address_space。但在其它结构体中被引用时,该指针的名字通常是 mapping。
117+
2. mount:表示一个文件系统被挂载的信息。
118+
3. file_system_type:表示一个文件系统类型,例如 ext4、proc、sys 等。
119+
94120
# 注册和注销文件系统
95121

96122
## struct file_system_type
@@ -133,6 +159,12 @@ struct file_system_type
133159
};
134160
```
135161

162+
内核中的所有 file_system_type 都是通过一根单向链表组织起来的,register_filesystem() 函数负责将新的 file_system_type 加入到这个链表中。
163+
164+
每个文件系统类型下都挂载了多个文件系统,比如 sda、sdb 都是 ext4 文件系统,这些 superblock 以链表的形式连接到 `file_system_type->fs_supers` 字段中。系统中所有的 superblock 也是通过一根双向链表进行连接。
165+
166+
<img src="https://img-blog.csdnimg.cn/direct/2bdd2062e61a41b182de277573ab32f4.png" alt="image-20241227120407496" style="zoom:75%;" />
167+
136168
在模块加载函数中,将文件系统注册到内核,需要做以下几步:
137169

138170
1. 初始化 `struct file_system_type` 结构体类型的实体,并填充相应的字段以及回调函数。
@@ -507,6 +539,10 @@ struct inode
507539
} __randomize_layout;
508540
```
509541

542+
每个文件系统都缓存了一定的 inode 数量到内存中。同一个文件系统的 inode 以双向链表连接起来,挂在 `superblock->s_inodes` 字段中。同时,内核中所有的 inode 被组织在了一个哈希表 inode_hashtable 上。
543+
544+
<img src="https://img-blog.csdnimg.cn/direct/c2c096ac10cd49878899428229ebfe98.png" alt="image-20241227141716401" style="zoom:75%;" />
545+
510546
一些可用于处理 inode 的函数如下:
511547

512548
1. new_inode():创建新的 inode,将 i_nlink 字段设置为 1,并初始化 i_blkbits, i_sb 和 i_dev。
@@ -588,6 +624,16 @@ inode 索引节点的相关操作由 `struct inode_operations` 结构描述。
588624
589625
访问 `struct inode` 中的 i_op 字段可以对索引节点的操作进行初始化和访问。
590626
627+
# mount
628+
629+
**mount 代表了一个文件系统被挂载到了某个地方。**只有被挂载的文件系统,才能通过 VFS 的目录树进行访问。
630+
631+
一个文件系统可能被多次 mount 到不同的地方,这样一个 superblock 会对应多个不同的 mount 结构,这些 mount 以双向链表的形式组织起来,挂在 superblock->s_mounts 字段。
632+
633+
被 mount 的目录称为一个 mount 点。目录也是一个 dentry,mount 通过 mnt_mountpoint 字段指向该 dentry。
634+
635+
<img src="https://img-blog.csdnimg.cn/direct/7b045be8277948d1a013fbc7538c9764.png" alt="image-20241227145405084" style="zoom:75%;" />
636+
591637
# file
592638
593639
**file 结构对应于由进程打开的文件,仅存在于内存中,并与 inode 索引节点关联。**它是最接近用户空间的 VFS 实体。结构字段包含用户空间文件的熟悉信息(访问模式、文件位置等),与之相关的操作由已知的系统调用(read, write 等)执行。

0 commit comments

Comments
 (0)