从零开始写个文件系统
简单的demo文件系统
tinyfs一个简单的文件系统,用于理解linux内核的文件系统 源码注释版:https://github.com/ruoniao/tinyfs
文件系统基本信息
文件系统的基本操作
- 创建(Create):
- 文件创建:创建一个新文件。通常通过系统调用如 open(使用 O_CREAT 标志)或 creat 实现。
- 目录创建:创建一个新目录。通过系统调用 mkdir 实现。
- 删除(Delete):
- 文件删除:删除一个文件。通过系统调用 unlink 实现。
- 目录删除:删除一个空目录。通过系统调用 rmdir 实现。
-
读(Read):从文件中读取数据。通过系统调用 read 实现,将文件内容读取到用户提供的缓冲区中。
-
写(Write):将数据写入文件。通过系统调用 write 实现,将用户提供的数据写入文件中。
- 打开(Open)和关闭(Close):
- 打开文件:通过系统调用 open 打开一个文件,并返回一个文件描述符。
- 关闭文件:通过系统调用 close 关闭文件描述符。
- 定位(Seek):改变文件的读写位置。通过系统调用 lseek 实现,设置文件描述符的位置,用于下一次读写操作。
-
重命名(Rename):改变文件或目录的名称。通过系统调用 rename 实现。
- 链接(Link):
- 硬链接:创建一个新的目录项,指向现有文件的相同数据。通过系统调用 link 实现。
- 软链接(符号链接):创建一个新的目录项,指向现有文件或目录的路径名。通过系统调用 symlink 实现。
- 获取属性(Get Attributes)和设置属性(Set Attributes):
- 获取文件属性:通过系统调用 stat 或 fstat 获取文件的元数据(如大小、权限、修改时间等)。
- 设置文件属性:通过系统调用 chmod、chown 等修改文件的元数据。
- 文件系统导航(Directory Navigation):读取目录:通过系统调用 opendir 打开目录,使用 readdir 读取目录项,最后用 closedir 关闭目录。
- 改变工作目录:通过系统调用 chdir 改变当前工作目录。
元数据
超级块
超级块是文件系统的重要数据结构,它包含关于文件系统的信息和元数据,定义了文件系统的基本参数和状态。
主要内容:
- 文件系统类型:标识文件系统的类型(如 ext4, xfs 等)。
- 总块数:文件系统中的块总数。
- 空闲块数:当前可用的块数。
- 空闲 inode 数:当前可用的 inode 数。
- 块大小:文件系统中块的大小。
- inode 大小:inode 的大小。
- 挂载状态:文件系统是否被挂载,以及挂载的相关信息。
- 时间戳:文件系统创建、挂载、卸载等操作的时间戳。
作用:
超级块用于文件系统的管理和维护,它提供了文件系统的整体信息,使得操作系统能够正确地读取和写入文件系统数据。超级块通常保存在文件系统的固定位置,确保系统重启或崩溃后能够恢复文件系统的状态。
inode 介绍
inode 是文件系统中的一个数据结构,代表一个文件或目录。每个文件和目录都有一个唯一的 inode,存储该文件或目录的元数据。
主要内容:
- 文件类型:文件、目录、符号链接等。
- 权限:文件的读、写、执行权限。
- 所有者和组:文件所有者的用户 ID 和组 ID。
- 文件大小:文件的字节数。
- 时间戳:文件的创建、修改、访问时间。
- 链接数:指向该 inode 的硬链接数量。
- 数据块指针:指向存储文件数据的块的指针列表。
作用:
inode 提供了文件或目录的所有元数据信息,使得操作系统能够管理文件的属性和数据存储位置。通过 inode,操作系统可以高效地访问文件内容和属性。
目录也是个文件
在 Unix 和类 Unix 文件系统中,目录本质上是一个特殊类型的文件,它包含了一系列目录项(directory entries),每个目录项记录了目录下的文件或子目录的名字和其对应的 inode 号。
目录项
目录项是目录文件中的一个条目,记录了目录下的文件或子目录的名字和对应的 inode 号。
主要内容:
- 文件名:目录下文件或子目录的名称。
- inode 号:文件名对应的 inode 号。
作用:
目录项提供了从文件名到 inode 的映射,使得操作系统能够根据文件名找到相应的 inode,从而访问文件的内容和属性。目录项的高效管理对于文件系统的性能至关重要。
元数据管理对性能的影响
元数据包括文件的所有属性信息(如 inode 信息、目录结构等),它们的管理对文件系统性能有显著影响。当一个目录的目录项数量过大,在目录中查找文件会非常缓慢
命名空间的管理
挂载命名空间是 Linux 命名空间的一种,用于隔离文件系统挂载点。每个挂载命名空间都有独立的挂载点视图,进程可以在自己的命名空间中挂载或卸载文件系统,而不影响其他命名空间。
存储管理
存储分配
连续分配
block 连续分配,优点是简单,索引迅速,随机访问支持好。缺点是删除文件会产生碎片,与内存分配碎片相似。创建或者增加文件长度时,开销大。ntfs格式就是连续分配
链式分配
像链表以管理block,优点时磁盘利用率高,数据可以不连续,分配空间可以时任意block,增删文件容易。 缺点是 随机访问效率低,所有块都需要从第一个块遍历过去。可靠性插,丢失一个block后续block都丢失。
索引分配
将每个block位置通过指针保存在索引节点表中,由于节点索引表空间有限,还可以通过间接分级索引的方式,将索引指针指向另一个节点索引表。ext2采用的是多级节点索引分配。优点是磁盘空间利用率高,类似链式分配,通过索引的方式使得随机访问效率也高。
空闲空间管理
bitmap位图管理
0表示未使用 1表示已经使用
链表管理
空闲空间管理性能
需要维护在内核和磁盘的数据一致性,当系统崩溃可能导致数据丢失,而且写回磁盘存在较高的延时,很大可能带来性能问题
Ext2文件系统案例
参考: https://www.kerneltravel.net/book/book/%E7%AC%AC%E4%B9%9D%E7%AB%A0Ext2%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F.pdf
块组及块组中的数据结构
在快组1中记录了超级快,组描述符,块位图,索引节点位图,索引节点表,数据区信息等元数据。
ext2的寻址方式
12个直接索引,3个间接索引