OS之存储管理—详解文件系统的实现方式(一)
磁盘使用的性能
采用缓冲区
有些系统有一块独立内存用作缓冲区缓存,假设其中的块将很块再次使用。有的系统是采用页面缓存来缓存文件数据,页面缓存采用虚拟内存技术,将文件数据按页面而不是按面向文件系统的块来缓存。采用虚拟内存来缓存文件数据,与采用物理磁盘块来缓存相比,更加的高效。包括Solaris、Linux、Windows,采用页面缓存来缓存进程页面和文件数据,这称为统一虚拟内存。
UNIX和Linux有的版本采用了统一缓冲区缓存。考虑文件打开和访问的两种方式,一种是通过内存映射;另一种是采用标准系统调用read()和write()。如果没有统一缓冲区缓存,那么可能会有如下情况:
系统调用read()和write()会通过缓冲区缓存,但是内存映射调用需要使用两个缓冲,即页面缓存和缓冲区缓存,内存映射先从文件系统中读入磁盘块,并存储在缓冲区缓存中。因此虚拟内存系统没有缓冲区缓存的接口,所以缓冲区缓存内的文件内容必须复制到页面缓存。这种情况称为双缓存。这样不仅浪费内存,而且浪费重要的CPU和I/O时间,同时,两种缓存之间的不一致性也可能导致文件破坏。
如果内存映射和read()与write()系统采用同样的页面缓存,这样有利于避免双缓存,并允许虚拟内存系统来管理文件系统数据,这种统一缓冲区缓存机制如下:
同步异步写入
文件系统的写入是同步还是异步也是影响I/O性能的一个问题。同步写(synchronous write)按磁盘子系统接收顺序来进行,并不缓冲写入。因此调入程序必须等待数据写到磁盘驱动器,在进行。对于异步写(asynchronous write)将数据先存在缓存后,就将控制返还给调用者。大多数的写都是异步的,然而元数据写,与其他一样,可以是同步的。操作系统经常允许系统调用open包括一个标志,以允许进程请求写入同步执行,例如数据库的原子事务使用这种功能。
页面置换算法
有的系统根据文件访问类型来采用不同的替换算法,来优化页面缓存。文件的顺序读写不应该采用LRU页面置换,因为最近使用的页面最后才会使用或根本不用,相反顺序访问可以通过采用称为随后释放和预先读取技术来加以优化。
随后释放是:一旦请求下一个页面,就从缓冲区删除一个页面。因为以前的页面可能不用,并且浪费缓冲区空间。
预先读取是:请求的页面和一些之后的页面可以一起读取并缓存,这些页面可能在当前页面处理之后再被请求。
故障恢复
文件和目录保存在内存和磁盘中,必须注意确保系统故障不能导致数据丢失或系统不一致。
一致性检查
文件系统可能在文件系统的元数据中记录其状态。在任何元数据修改的开始,设置状态位以表示元数据保持置位,则运行一致性检查程序。
一致性检查程序(consistency checker),会比较目录结构的数据和磁盘的数据块,并且试图修复发现的不一致。
基于日志的文件系统
一致性检查基本允许结构破坏并且在恢复时修复它们,但是存在很多问题,一个是不一致可能是无法修复的,将会导致文件和甚至整个目录的丢失。另一个是一致性检查可能需要认为干预来解决冲突。同时,一致性检查还需要很大的系统时间和时钟时间。那么我们可以通过应用基于日志恢复技术到文件系统的元数据更新。
从根本上说,所有元数据修改按顺序写到日志中。执行特定任务的一组操作称为事务(transaction)。一旦这些修改写到这个日志,就可认为是已经提交,系统调用可返回到用户进程以便继续执行。同时,这些日志条目对真是文件系统结构进行重放。随着更改,通过指针更新表示哪些操作已经完成和哪些任然没有完成,当整个提交事务已经完成,就可以从日志文件中删除它(日志文件实际上是个环形缓冲区)。当环形缓冲区写到空间末尾的时候,会从头继续,覆盖掉以前的旧值。日志文件可能是文件系统的一个单独的部分,甚至在单独的磁盘上,采用分开读/写磁头可以减少磁头的竞争和寻道时间,会更有效但更复杂。
其他解决方法
网络家电WAFL文件系统和Solaris的ZFS文件系统,采用另一种一致性检查。这些系统从不采用新数据来覆盖块。相反,事务将所有数据和元数据更改写到新块,当事务完成时,指向这些块旧版的元数据结构被更新到指向这些新块。然后文件系统可以删除旧的文件指针和旧的块,以便可以重用。如果保留旧的指针和块,则创建了快照。这个快照是在最后更新之前的文件系统的一个视图