文件系统的使用
-
文件的命名
- 对于Unix系统 ,文件的拓展名只是一种约定,并不给操作系统传递什么信息
- 在Unix中,拓展名甚至可以有多个,如
homepage.hitml.zip
表示一个被压缩过的HTML格式的网页文件 - 对于Windows系统,文件拓展名是有实际意义的,用户可以在操作系统中注册拓展名,并规定那个程序打开这个拓展名
-
文件类型
- 普通文件
- ASCII 文件
- 可以显示,打印以及用文件编辑器编译
- 二进制文件
- 只能被执行这个文件的程序理解
- ASCII 文件
- 字符特殊文件
- 抽象输入输出
- 块特殊文件
- 抽象打印机,网络等
- 普通文件
-
目录
- 一种特殊的文件
- 内置两个目录项
- · 指向当前目录
- ·· 指向父目录
- 根目录的 ·· 指向自己
- 每个进程都有自己独立的工作目录
- 当需要读取大量文件的时候,为了避免输入路径的麻烦,可以先切换工作目录到待读取目录,读取完后再切换回来
- 库过程最好不要切换工作目录
cp /usr/lib dic.txt .
将dic.txt文件复制到当前目录
文件系统的实现
- 磁盘块
- 磁盘访问的绝大多数时间都花费在寻道和旋转延迟上,读写时间占比很小
- 由于磁盘的读写很慢,因此不可能1bit1bit的读,而是采用磁盘块作为最小的读取单元
- 因此磁盘块也是最小的文件大小
- 例如Windows中文件最小为1Kb
- 磁盘块的大小
- 块太小则一个文件的块数量太多,读取太慢
- 块太大则小文件经常写不满一个块,浪费空间
- 绝大多数文件都是小文件
- 空闲块的组织
- 使用链表
- 每个链表项占用大
- 在链表的基础上,加上一个块计数,于是一个表项不止一个块
- 当磁盘碎片较多时效率低,因为还要多余空间储存计数
- 使用位图
- n个块的磁盘需要n位的位图,0为空闲块
- 使用链表
- 链接
- 链接技术允许在多个目录中出现同一个文件
- 硬链接
- 指向同一个i节点
- 增加了文件的i节点(i-node)的计数
- i节点是一个结构体,包含文件的方方面面的信息
- 不占用空间
- 缺点
- 系统无法找到指向该文件的所有目录项并删除他们
- 符号链接
- 又叫做软连接
- 建立一个类型为LINK的新文件,该文件只包含他所链接文件的路径名
- 当操作系统查看到所读的文件是link类型时,则去读文件所含链接的文件
- 只需要提供一个机器的网络地址和相对路径就可以访问全球任意地点机器上的文件
- 缺点
- 读取时需要额外的开销(因为要根据路径找到对应的文件i节点)
- 储存链接文件需要额外的空间和i节点
- 文件在磁盘中的分配
- 连续分配
- 一般用在CD等文件不再改变的设备上
- 链表分配
- 为每个文件构造一个磁盘链表
- 由于读取文件的任何部分都要从文件头开始寻找,而访问磁盘非常慢,所以随机访问很慢
- 内存分配表
- 将文件所在的磁盘块存放在内存中的文件分配表中
- 优点在于快速的随机访问
- 缺点在于分配表包含磁盘中的所有块,不能较好支持大型磁盘
- 使用i节点
- 见下一小节
- 见下一小节
- 连续分配
- i节点
- 给每个文件赋予一个i节点的结构,只有当对应文件打开时,i节点才放入内存中
- 每个节点储存的磁盘数量是固定的,因此最后一个指针指针指向一个包含额外磁盘块地址的块地址
- i节点中还含有文件的所有属性
- 使用i节点组织的文件在每次访问的时候都会读取磁盘两次,一次访问i节点,一次访问块,为了降低寻道实现,最好让i节点和对应的块离的近一些,所以i节点一般放在磁盘的中部而不是最外面
-
目录的实现
- 有了i节点,目录项就只需要文件名和节点号了
- 为了实现任意长度的文件名,目录项将文件名放在目录后的堆中
- 当目录中文件很多时,为什么实现快速的文件查找,采用哈希表组织文件
-
虚拟文件系统
- 在同一个操作系统下,可能有不同的文件系统,为了统一和抽象,采用了虚拟文件系统
- 上层接口遵循POSIX标准
- 下层通过VFS接口调用对应的不同的文件系统
-
文件系统的一致性
- 块一致性检查
- 读取所有i节点,记录所有被文件使用的块号
- 检查空闲表或位图,记录所有空闲块号
- 如果每个块两者加起来不是一,这个块就有问题
- 文件一致性检查
- 遍历目录树,和i节点表比较
- 块一致性检查
-
磁盘布局
- 如下图, 系统将磁盘划分为多个分区,每个分区有独立的文件系统
- 0号分区为MBR(主引导记录),用来引导计算机,结尾是分区表
- 分区中的第一个块为引导块,转载操作系统(为统一起见,即使该分区没有操作系统也有引导块)
- 超级块包含了全局文件的信息,会在下面详述
- Inode块包含了该分区所有inode节点
- 超级块
- 典型信息有硬盘已用空间、数据块可用空间、inode节点等
- 当操作系统启动后,系统内核会把超级块中的内容复制到内存中,并周期性的利用内存里的最新内容去更新硬盘上的超级块中的内容
- 当操作系统意外当机或者因为断电而造成的意外事故时,内存中的超级块信息没有及时保存到硬盘中,此时文件系统的完整性就会受到破坏
- 关于iNode块和超级块,这篇文章解释的很好:https://blog.csdn.net/yuyi_000/article/details/51473290
文件系统分类
日志文件系统
-
日志是磁盘上的一种特殊的分配区域,其写入被存储在事务中;如果该事务完成磁盘写入,则日志中的数据将提交给文件系统自身。如果系统在该操作提交前崩溃,则重新启动的系统识别其为未完成的事务而将其进行回滚,就像从未发生过一样。这意味着正在处理的文件可能依然会丢失,但文件系统 本身 保持一致,且其它所有数据都是安全的
-
三种写入方法
- 数据模式
- 索引节点(存有文件信息)和文件都被写入日志
- 所有写到存储设备的数据都要写两次
- 流失风险最低,性能最差
- 有序模式
- 大部分系统的默认模式
- 只有索引节点数据写入日志,但只有数据写入后日志才删除
- 回写模式
- 只有索引节点数据写入日志,不控制文件数据何时写入
- 数据丢失风险高
- 数据模式
-
常见的日志文件系统
etx[1234]
、Reiser
、XFS
-
将磁盘分为一个个日志段,每个单独段包含i节点,目录块,数据块等,日志开头为该段的摘要
- 所有的写操作最开始都缓存在内存中,然后周期性地写入磁盘中的日志段
- 此时i节点分散在日志中,难以通过哈希表定位,所以需要维护一个节点表
- 需要一个清理线程定期扫描日志进行压缩
- 奔溃处理
- 移除文件所要的三个步骤
- 第一步:在目录中删除文件
- 如果奔溃,i节点和文件快将不会被任何文件获得,也不会再分配
- 第二步: 释放i节点到空闲i节点池
- 如果奔溃,磁盘块会丢失
- 第三步: 将磁盘块归还到空闲磁盘块池
- 第一步:在目录中删除文件
- 移除文件所要的三个步骤
- 写入操作在执行前,先加入日志项,在操作执行完毕后才擦除,如果系统在写入完成前奔溃,恢复后可以查看日志并继续未完成的操作
- 所有写入日志操作必须是幂等的
- 幂等就是同一个操作可以重复执行很多次而不会带来破坏
- 幂等操作:将块n标记为空闲的
- 非幂等操作: 将i节点文件计数器加1
- 上面删除文件的第一二步操作是幂等的,第三步不是
-
参考
写时复制文件系统
- 常见的写时复制文件系统
ZFS
、Btrf