0%

Linux文件系统

文件

Linux中文件的概念并没有那么纯粹,不单单指的是磁盘上的文件。Linux中只要是字节序列构成的载体,都可以是文件,比如I/O设备、socket套接字等。总的来说大致分为以下几类:

  • 普通文件。即磁盘上的文件
  • 目录文件。即目录
  • 链接文件。Windows上称为快捷方式,但是在Linux中链接文件还分为软链接(符号链接)与硬链接
  • 设备文件。Linux中将设备看作文件来进行管理,分为块设备与字符设备。
  • socket文件。用于网络通信
  • 管道文件。用于IPC

文件系统结构

在Linux中,文件系统并不是像Windows中的那样分为一个一个盘,而是以挂载到别的文件系统的形式存在的。这种结构可以简单地看成树型结构,根结点则是根文件系统。

文件系统

Linux可以支持很多文件系统,这些文件系统之间的数据也可以是互通的。Linux使用了VFS这一结构来管理文件系统。

VFS即虚拟文件系统,在各种具体的文件系统之上建立一个抽象层,屏蔽了不同文件系统之间的差异。这种抽象层其实也像POSIX标准一样,为了屏蔽底层的细节而设计的。

VFS

VFS主要有如下的四个对象类型:

  • 超级块(struct super_block)。超级块代表一个已经安装的文件系统,存储着该文件系统的有关信息,比如文件系统的类型、大小、状态等。
  • 索引结点(struct inode)。索引结点对象表示存储设备上的一个实际的物理文件,存储该文件的有关信息,比如权限、大小以及创建时间等。
  • 目录项(struct dentry)。目录项描述了文件系统的层次结构,不管是目录还是普通的文件,都是一个目录项对象。
  • 文件(struct file)。文件对象代表已经被进程打开的文件,主要用于建立进程和文件之间的对应关系。

值得注意的是,目录项并不是存在于磁盘中的信息,而是存在于内存当中,相当于磁盘的缓存。

文件

文件对象描述已经打开的文件,对于进程来说,能够直接进行处理的是文件,而不是超级块之类的。对于每个inode,可以对应多个文件对象,而一个文件对象只能对应一个inode。文件对象包含了对文件的相关操作struct file_operations,包括打开、关闭、读写等等。

与文件系统相关的结构

超级块中包含了一些其他的文件系统有关的结构体,例如struct file_system_type,表示文件系统类型。对于ext3文件系统来说定义如下:

1
2
3
4
5
6
7
static struct file_system_type ext3_fs_type = {
.owner = THIS_MODULE,
.name = "ext3",
.get_sb = ext3_get_sb,
.kill_sb = kill_block_super,
.fs_flags = FS_REQUIRES_DEV,
};

struct vfsmount则包含了文件系统挂载的信息,包括挂载点、根结点等。

与进程相关的结构

每个进程都有自己的根目录与当前工作目录,例如在shell中,可以使用pwd(print working directory)命令来打印当前工作目录。除此之外,进程还需要记录自己打开的文件,进程打开的文件用struct files_struct来表示,里面就包括了struct file数组,记录已经打开的文件信息。

inotify机制

简单来说,inotify机制是用来监听文件的变化的,类似与设备发送中断来表示设备状态发生了变化,操作系统也会发送信号来表示文件发生了变化,而这一点在Linux是通过inotify机制来实现的。

每个inode结点上都有一个inotify_watches字段,指向了该inode对象的监控列表,一个watch实例是一个struct inotify_watch结构的实例,代表了对该inode的监控请求,其中就包含了事件处理函数。

inotify的实现原理是,在各个文件操作函数的hook通过inode的成员inotify_watches找到监控列表,然后再通过监控列表找到事件处理函数,然后再进行处理。