文件系统体系结构
文件系统是对一个存储设备上的数据和元数据进行组织的机制。Linux 支持许多种文件系统,从日志型文件系统到集群文件系统和加密文件系统。Linux和Unix并不使用设备标志符(如设备号或驱动器名称)来访问独立文件系统,而是通过一个将整个文件系统表示成单一实体的层次树结构来访问它。总体上说 Linux 下的文件系统主要可分为三大块:一是上层的文件系统的系统调用,二是虚拟文件系统 VFS(Virtual Filesystem Switch),三是挂载到 VFS 中的各实际文件系统。
VFS使得Linux可以支持多个不同的文件系统,VFS做为文件系统接口的根层,记录当前支持的文件系统以及当前挂载的文件系统。Linux以一组通用对象的角度看待所有文件系统,这些对象是超级块(super block)、inode、目录和文件。
超级块在每个文件系统的根上,描述和维护文件的状态。超级块结构表示一个文件系统,包含管理文件系统所需的信息,包括文件系统名称、文件系统的大小和状态、块设备的引用和元数据信息。
文件系统中管理的每个对象(文件或目录)在Linux中表示为一个inode。inode包含管理文件系统中的对象所需的所有数据(包括可以在对象上执行的操作),它具有唯一标识符。
目录用来实现文件名和inode之间的映射,维护目录和文件之间的关系。系统中有一个目录缓存用来保存最近使用的目录。
在Linux有两种方法对文件进行操作:标准IO(带缓冲的IO)和文件IO(不带缓冲的IO)。
标准IO(带缓冲的IO)
标准IO(带缓冲的IO)是借助文件结构体指针(FILE)来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。
标准IO(带缓冲的IO)的特点是:在内存开辟一个“缓冲区”,为程序中的每一个文件使用。标准IO提供三种类型的缓冲:全缓冲、行缓冲和不带缓冲。全缓冲就是在填满标准IO缓冲区后才进行实际IO操作;行缓冲就是在输入输出中遇到换行符时标准IO执行IO操作;不带缓冲就是标准IO不对字符进行缓冲存储。一般来说,标准出错是不带缓冲,打开至终端设备的流是行缓冲的,其他所有流则是全缓冲的。我们可以使用setbuf、setvbuf更改缓冲类型。
对一个打开的流,可以有三种不同类型的非格式化IO对其进行读、写操作。
每次一个字符,使用fgetc、getc函数(这两个函数的区别就是getc可以被实现为宏,而fgetc则不能实现为宏);
每次一行,使用fgets、gets(对于fgets,必须指定缓冲区的长度n,在实际应用中这个长度可以指定为FILENAME_MAX);
直接IO,使用fread、fwrite(这两个函数通常用来读或写一个二进制数组,或者读或写一个结构),这种IO只能读在同一系统上已写的数据;
包括:fopen、fclose、fread、fwrite、fgetc、fgets、fseek、rewind、fputs、fputc、ungetc等。
文件IO(不带缓冲的IO)
文件IO(不带缓冲的IO)依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出。文件IO(不带缓冲的IO)使用文件描述符对文件进行管理,文件描述符是一个非负整数,由open返回的文件描述符一定是最小的未用描述符数值。write、read系统调用的效率取决于自己指定的缓存。
包括:open、close、create、read、write、lseek等。
一个例子
该例子使用标准IO对一个配置文件进行解析:如果配置文件中有配置信息或用户通过命令行指定了参数则打印出配置信息,否则打印出缺省信息。程序通过fgetc对文件流的进行字符操作,去掉注释和其他不需要的数据。注:如果对文件流进行行操作(通过fgets),那么可以使用sscanf对读出的行进行字符串分割,提取出相应的配置信息。
运行结果: