linux 文件系统

一. 存储设备分区

文件系统的最终目的是把大量数据有组织的放入持久性(persistant)的存储设备中, 如硬盘和磁盘. 这些设备的存储能力具有持久性, 不会应为断电而消失; 存储量大, 但读取速度慢.

最开始的区域是 MBR, 用于Linux 开机启动.
剩余的空间可能分成数个分区(partition), 每个分区有一个相关的分区表(partition table), 记录相关的分区信息. 这个分区表存储在分区之外. 分区表说明了对应分区的起始位置和分区大小.

存储设备分区

典型的Linux分区

分区的第一个部分是启动区(boot block), 主要为计算机开机服务. Linux 开机之后, 会首先载入 MBR, 随后 MBR 从某个硬盘的启动区加载程序.该程序负责进一步的操作系统的加载和启动. 为了方便管理, 即使某个分区中没有安装操作系统, Linux 也会在该分区预留启动分区.

启动区之后的是 超级区(super block) : 它存储有文件系统的相关信息, 包括文件系统的类型, inode 的数目, 数据块的数目.

随后是多个 inode, 他们是实现文件存储的关键. 在 Linux 系统中, 一个文件可以分成几个数据块存储. 每个文件对应一个 inode. 这个 inode 包含多个指针, 指向该文件各个数据块. 当操作系统需要读取文件时, 只需要对应 inode 的 地图, 收集起分散的数据块就可以获取到文件.

真正存储数据的是数据块 (data blocks)

二. inode

文件是文件系统对数据的分割单元. 文件系统用目录来组织文件, 赋予文件上下分级的结构. 在硬盘上实现这一分级结构的关键, 是使用 inode 来虚拟普通文件和目录文件对象.

文件元数据用来记录文件的大小,属组,属主,修改日期等相关信息, 元数据并不包含在文件的数据中, 而是由操作系统维护的. 元数据包含在 inode 当中. 每个 inode 有一个唯一的整数彪悍(inode number) 表示.

inode_structure
在保存元数据, inode 是文件从抽象到具体的关键.

每个inode能够存储的数据块指针总数是固定的。如果一个文件需要的数据块超过这一总数,inode需要额外的空间来存储多出来的指针。

目录文件也有inode

当我们读取一个文件时,实际上是在目录中找到了这个文件的inode编号,然后根据inode的指针,把数据块组合起来,放入内存供进一步的处理。
当我们写入一个文件时,是分配一个空白inode给该文件,将其inode编号记入该文件所属的目录,然后选取空白的数据块,让inode的指针指像这些数据块,并放入内存中的数据。

三. 文件描述符与文件共享

在 Linux 的进程中, 当我们打开一个文件时, 返回的是一个文件描述符. 这个描述符是一个数组的下标, 对应数组元素为一个指针. 有趣的是, 这个指针并没有直接指向文件的 inode, 而是指向一个文件表格(因为不仅需要记录inode , 还需要记录文件的读写状态, 读写位置等信息), 在通过该表格, 执行加载到内存中的目标文件的 inode.

文件描述符
每个文件表格中记录了文件打开的状态(status flags), 比如只读,写入等, 还记录了每个文件的当前读写位置(offset). 当有两个进程同事打开同一个文件时, 可以有两个文件表格, 每个文件表格对应的打开状态和当前位置不同, 从而支持一些文件共享的操作, 比如同时读取.

要注意的是进程fork 之后的情况, 子进程将只复制文件描述符的数组, 和父进程共享内核维护的文件表格和 inode, 此时要特别小心程序的编写.

[参考]

http://www.cnblogs.com/vamei/p/3506566.html