文件系统基础知识
1.文件类型
普通文件(regular file):包括文本文件和二进制文件。通过open或creat系统调用函数可以创建一个普通文件。
目录文件(directory file):也称为目录,一个目录的内容即为该目录下的文件和其他子目录。通过mkdir命令可创建一个目录。通过ls -l某个目录文件时,可以看到该文件的属性的第一项为d,即表示目录文件。
设备文件(device file):Linux将硬件设备也当作文件来处理,通过mknod命令可以创建一个设备文件。通常设备文件分为字设备文件(character special file),比如键盘和鼠标等;还有块设备文件(block special file),比如硬盘和光驱等。
链接文件(symbolic link):也称为符号链接,通过ln命令可以创建一个符号链接。符号链接文件本身就是一个文件,这种文件的内容则是另一个文件(即源文件)的路径。对符号链接进行读写等基本操作时,系统会自动将其转化为对源文件的相应操作。通过ls -l某个符号链接文件时,可以看到文件属性的第一项为l,即表示目录文件。
管道文件(pipe):用于进程间通信,也称为FIFO文件。通过系统调用pipe可以创建一个管道。管道文件在使用上和普通文件没有什么太大的区别,只不过这种文件不像普通文件那样存储与磁盘上,而是存储在内存中。
套接字文件(socket):主要用于网络通信,也可以用于一台主机上的进程间通信。
2.Linux文件结构
Linux采用树型结构将所有文件组织起来,也就是说,每一个Linux系统就只对应一个这样的树型结构。windows操作系统也采用树型结构,但却是每个分区对应一个树型结构。下面对Linux根目录下的一些常见子目录进行说明:
/bin:存放二进制的可执行的命令文件,我们通常所使用的命令就是来自这里。比如ls,cat等。
/sbin:存放系统管理命令的目录,即为使用前要加sudo的那些命令,比如fdisk等。
/mnt:存放用户临时安装其他文件系统的目录。
/dev:存放设备文件的目录。
/etc:存放系统管理和配置文件的目录。
/home:系统中所有用户主目录的汇总。通过/home/username可以访问某个用户的主目录。
/tmp:公共的临时文件目录。相对的,每个用户在其主目录下也有私有的临时文件目录。
/lib:标准程序设计库,又叫做动态链接共享库。
/proc:这个目录存在与内存中,不占用磁盘空间。该目录存放的是对内存的一次映像,我们每打印一次/proc目录,显示的就是当前内存的状态。
虚拟文件系统
Linux可支持数十种文件系统,不同的文件系统可以同时共存于一个系统之中。这些不同类型的文件系统并不是各自封闭的,而很可能会进行文件复制和移动等。比如,我的PC中装有双系统(比如ubuntu+winXP),现在我要将XP系统E盘中的test.doc文件拷贝到ubuntu系统中的主目录下。我们知道,XP的文件系统类型是FAT,而Linux主目录的文件系统类型是ext3,我们如何使用一种统一的“语言”来支持这种不同文件系统上文件的移动和复制?虚拟文件系统(Virtual FileSystem,VFS)就扮演的这样的角色,即支持跨越不同文件系统或存储设备的文件操作。
VFS是在各种具体的文件系统之上建立了一个抽象层,它屏蔽了不同文件系统间的差异。它之所以可以将各种文件系统纳入其中,是因为它提供了一个通用的文件系统模型。在内核中,这个通用的模型具体的表现为一组统一的抽象接口和数据结构。每个文件系统都必须实现这些统一接口,并在组织结构上与该模型保持一致。
VFS相当于一个万能插销座,具体的文件系统相当于插销座内部的电路实现。不管是两头插销还是三头插销,甚至未来出现的单头插销都可以使用这个万能的插座,使用根本不必考虑这个插座内部是如何实现的。
关于VFS更加全面的解说可以看这里。
VFS中的数据结构
上面说到,VFS是通用的文件系统模型。那么,这个通用性具体如何表现出来?VFS主要通过一组数据结构来描述文件对象。其中有四个基本的结构体:
超级块(struct super_block):它描述一个已安装了的文件系统。
索引结点(struct inode):它描述一个文件。
目录项(strcut dentry):它描述文件系统的层次结构。一个完整路径的每个组成部分都是一个目录项。比如打开/home/edsionte/code/hello.c时,内核分别为/,home/,edsionte/,code/,hello.c创建相应的目录项。
文件(struct file):它描述一个已被进程打开的文件。
VFS采用面向对象的思想,在上述每一个结构体中即包含描述每个文件对象属性的数据,又包含对这些数据进行操作的函数指针结构体。也就是说,上述四个基本的结构体中,每一个结构体中又嵌套了一个子结构体,这个子结构体包含了对父结构体进行各种操作的函数指针。
上述文字是对VFS主要的几个结构体大致的说明。下文中,将从代码的角度分析这些结构体。