UNIX高级环境编程(16)文件系统 < 雨后 >

来点绿色放松一下眼睛吧 :)

雨后

 

文件系统是对文件和目录的组织集合。

 

一 设备文件

设备文件和系统的某个设备相对应。

设备驱动程序

  • 处理设备的所有IO请求。
  • 提供了一致的API接口,对应于系统调用的open, close, read, write, mmap以及ioctl,屏蔽了底层设备的差异。

设备的类型

  • 字符型设备:基于每个字符来处理请求,例如终端和鼠标、键盘。
  • 块设备:按数据块处理请求,通常数据块是512字节的整数倍。例如硬盘和磁带。

设备ID

  • 每个设备文件都有主、辅设备文件ID。主文件ID标识一般的设备等级,内核会根据主ID查找与该类设备对应的设备驱动程序。
  • 辅ID能够在一般等级中唯一标识特定设备。
  • 文件的inode中记录了主辅ID

 

二 磁盘和分区

2.1 磁盘驱动器

磁盘驱动器是一种机械装置,由一个或多个高速旋转的盘片组成。通过在磁盘上快速移动读写磁头,便可获取/修改磁盘表面的磁性编码信息。

其结构见下图。

磁道

 

磁头

磁道:磁盘表面的信息存储在称为磁道的一组同心圆上。

扇区:磁道被划分为若干扇区。

物理块:扇区包含一系列物理块,物理块的容量一般为512字节,代表了驱动器可以读写的最小信息单位。

寻道时间:读写磁盘信息,首先,磁头要移动到相应磁道,这段时间叫做寻道时间。

旋转延迟:然后,驱动器要等待相应的扇区旋转到磁头下。

传输时间:最后,从所请求的块上传输数据。

执行上述操作所耗费的时间总量通常以毫秒为单位。

 

2.1 磁盘分区

分区:可将每块磁盘换分成一个或多个不重叠的分区。内核则将每个分区视为位于/dev路径下的单独设备。

磁盘分区可容纳任何类型的信息,通常包括:

  • 文件系统:用来存放常规文件
  • 数据区域:可做为裸设备对其进行访问,一些数据库管理系统会这样使用。
  • 交换区域:供内核的内存管理之用。

可使用Linux专有文件/proc/swaps来查看系统中当前已激活交换区域的信息,其中包括每个交换区域的大小,以及在用交换区域的个数。

 

三 文件系统

文件系统是对常规文件和目录的组织集合。

Linux的强项之一是支持种类繁多的文件系统。

以ext2为例来介绍文件系统。

3.1 文件系统结构

逻辑块:在文件系统中,用来分配空间的基本单位是逻辑块,也就是文件系统所在物理设备上若干连续的物理块。在ext2文件系统上,逻辑块的大小为1024、2048或4096。

磁盘分区和文件系统之间的关系如下图所示

NewImage

文件系统由以下几个部分组成:

  1. 引导块:总是作为文件系统的首块。引导块不为文件系统所用,只是包含用来引导操作系统的信息。
  2. 超级块:紧随引导块之后的一个独立块,包含与文件系统相关的参数信息,包括:
    1. i节点表容量
    2. 文件系统中逻辑块的大小
    3. 以逻辑块计,文件系统的大小
  3. i节点表:文件系统中的每个文件或目录在i节点表中都对应着唯一一条记录。这条记录登记了和文件相关的各种信息。
  4. 数据块:文件系统的大部分空间都用于存放数据,以构成驻留于文件系统之上的文件和目录。

3.2 i节点

i节点维护的信息如下

  • 文件类型
  • 文件属主
  • 文件属组
  • 3类用户的访问权限
  • 3个时间戳:对文件的最后访问时间、文件的最后修改时间、文件状态的最后改变时间
  • 指向文件的硬连接数量
  • 文件的大小,以字节为单位
  • 实际分配给文件的数据块,以512字节为单位
  • 指向文件数据块的大小

ext2中的i节点和数据块指针

文件的数据块不一定连续,为了定位文件数据块,inode维护了一组指针,如下图所示:

NewImage

在ext2中,每个inode包含15个指针,其中

  • 前12个指针指向前12个数据块在文件系统中的位置。
  • 第13个指针是一个一重间接指针
  • 第14个指针是一个二重间接指针
  • 第15个指针是一个三重间接指针

这样设计的意图是:

  • inode结构固定大小固定,并支持任意大小的文件
  • 可以不连续地存储文件,并支持lseek随机访问,内核只需要计算所要遵循的指针
  • 对于有大量小文件的系统中,可以对数据进行快速访问,一次搜索就可以访问。

四 虚拟文件系统(VFS)

Linux所支持的各种文件系统,其实现细节均不相同。虚拟文件系统是一种内核特性,通过为文件系统操作创建抽象层来解决各种文件系统之间的差异问题。

NewImage

原理:

  • VFS针对文件系统定义了一套通用接口,所有与文件交互的程序都会按照这一接口来进行操作。
  • 每种文件系统都会提供VFS接口的实现。

这样一来,程序只需要理解VFS接口,而无需过问具体文件系统的实现细节。

五 日志文件系统

如果系统突然崩溃,对文件的更新的只完成了一半,文件系统元数据也将处于不一致状态。

而系统对文件系统进行一致性检查需要遍历整个文件系统,这是一个非常耗时的操作。

日志文件系统就是为了解决这个问题。具体做法是

  • 在实际更新元数据之前,日志文件系统会将这些更新操作记录于专用的磁盘日志文件中。
  • 对元数据更新的操作记录是以事务的方式进行的,这样确保总是将文件元数据事务作为一个完整单元来提交。

需要注意的是,通常日志文件系统知会确保元数据的一致性,不会记录文件数据。因此,一旦系统崩溃,可能会造成数据丢失。

六 单根目录层级和挂载点

Linux上的所有文件系统中的文件都位于单根目录树下,其他文件系统都挂载在根目录下。

挂在命令:

mount device directory

 

下面通过实例来说明挂载后的文件系统的层级关系。

不带任何参数来执行mount命令,可以列出当前已挂载的文件系统。

NewImage

挂载点和设备的映射关系如下

NewImage

七 虚拟内存文件系统:tmpfs

Linux支持驻留于内存中的虚拟文件系统,对于应用程序来说,此类文件系统看起来与任何其他文件系统别无二致,不过二者的重要的差别是:

  • 由于不涉及磁盘访问,虚拟文件系统的文件操作速度极快
  • 该文件系统不仅可以使用RAM,而且在RAM资源耗尽的情况下,还会利用交换空间
  • 默认情况下,允许tmpfs文件系统的大小提高至RAM容量的一半
  • 一旦写在tmpfs文件系统,或者遭遇系统崩溃,那么该文件系统中的所有数据都将丢失

挂在虚拟文件系统命令如下:

mount -t tmpfs source target
其中source只有在/proc/mounts中可以看到,没有其他用途。
例如:
NewImage
 
除了用于用户应用程序以外,tmpfs文件系统还有以下两个特殊用途:
  • 由内核内部挂在的隐形tmpfs文件系统,用于实现System V共享内存和共享匿名内存映射。
  • 挂在与/dev/shm的tmpfs文件系统,为glibc用以实现POSIX共享内存和POSIX信号量。
 
 
参考资料
 
《Linux/Unix系统编程手册(上册)》 第14章
posted @ 2016-06-02 19:45 suzhou 阅读(...) 评论(...) 编辑 收藏