文件系统接口介绍及要求

这里我们将从用户的角度,介绍文件系统对用户的接口。

文件系统接口要求

我们要求文件系统需要支持以下功能(你可以用多个系统调用来实现,如用 seek + read 来实现读,但不接受过于复杂的实现逻辑):

  • 新建目录及文件:可在任何位置新建目录及文件
  • 删除目录及文件:可删除除根目录以外的任何目录及文件
  • 修改目录名及文件名:可修改目录及文件的名字
  • 读取目录及文件:可读取特定位置的特定长度的内容
  • 写入目录及文件:可写入特定位置的特定长度的内容
  • 移动目录及文件:可移动目录及文件到另一个位置

我们建议实现以下功能:

  • 文件和目录的权限控制
  • 文件和目录的时间戳

文件系统接口介绍

这里我们按照 Linux 的文件系统接口来介绍文件系统的接口,你不一定要严格按照这里的接口来实现。

索引节点 Index Node (inode)

在类 Unix 操作系统中,每个文件都会有一个 inode 与之对应,inode 储存了文件的元数据信息,如文件大小、文件权限、文件所有者等。当我们需要访问文件时,我们会先通过文件名找到 inode,然后通过 inode 找到文件的数据块。通过文件名找到 inode 的过程由文件系统的设计决定。

在类 Unix 操作系统中,文件名不是文件的属性,其只用于索引。这为硬链接提供了便利,只要两个文件指向的 inode 相同,那么这两个文件就是硬链接。为了方便删除文件,inode 中会记录文件的硬链接数,当硬链接数为 0 时,文件会被删除。

目录索引

在类 Unix 操作系统中,目录的作用是一层层地找到文件的 inode。目录也是一个文件,其记录了当前目录的文件和子目录的 inode,以及自己和父目录的 inode。对于根目录,其父目录的 inode 为自己的 inode。

因此,找文件的过程就是从根目录开始(根目录的 inode 会在文件系统驱动初始化的时候找到),找到下一层的目录 inode,进而找到下一层目录的内容,这样逐层找到文件的 inode。

文件描述符 File Descriptor (fd)

文件描述符 (File Descriptor, fd) 是一个整数,其用于标识一个文件。当我们打开一个文件时,文件系统会返回一个文件描述符,之后我们可以通过这个文件描述符来操作文件。文件描述符是进程的属性,因此不同进程的文件描述符可以指向同一个文件。

task_struct 中,我们会记录文件描述符表,其记录了文件描述符和 inode 的对应关系。

实际上,在 Linux 中,文件描述符还可以只带其他的东西,如网络连接、管道、外部设备等。

系统调用

如果要使用文件,需要先打开文件。对应的系统调用有 open(其实还有其他接口,但是我们只需要管 open 即可)。open 会返回一个文件描述符,之后我们可以通过这个文件描述符来操作文件。open 还可以通过 flags 来指定打开文件的方式,如只读、只写、读写、创建文件等。具体请看 manpage

对于文件读写,在 Linux 中有两套方法,一套是先 lseek 到对应的位置,再 readwrite,另一套是直接 preadpwritepreadpwrite 会直接指定初始的位置,而 readwrite 不会。

使用完文件后,需要关闭文件。对应的系统调用是 closeclose 会释放文件描述符,之后这个文件描述符就不再指代该文件了。