今日推荐文章:https://cloud.tencent.com/developer/article/2464044 文章详细讲解了数据库更新过程中与缓存中出现的短暂不一致性,以及每种解决方案的适用场景,看完后对于缓存一致性会有更加深入的了解
操作系统中的文件模块是很重要的一个模块,可以说,我们能够在计算机上按照所需编写指定的文档、程序,都离不开文件系统的构造与一些典型机制,本篇文章旨在从简单的xv6系统到Linux中Ext3文件系统(现在已经发展到了Ext4)中一些很典型的文件恢复机制,关于本篇文章的前置知识在这里:https://cloud.tencent.com/developer/article/2462526 看完你可以更好地理解本篇文章的内容
首先我们需要了解崩溃恢复这个概念,我们知道,当我们编辑一个文件时,如果此时电脑突然关机,再次重启后,编辑的文件会原封不动地展示出来,这个过程就是所谓的崩溃恢复过程,在这个过程中有很多值得探讨的问题,例如:
操作系统如何保证能够将原本编辑的文件内容展现出来,用户已经编辑的文件内容存储在了哪里?
如果有多个写文件操作,那么操作系统如何依次将所有的文件进行恢复?
如果在写文件写到一半的过程中没有保存,那么这些文件能否被持久化到磁盘中?
类似于这样的问题还有很多,实际上在操作系统这个多进程同时并行的环境中,如何能够保证多个进程对于同一片内存区域读写的正确性都是一个极大的考验,而能否解决这些问题也就是文件系统设计过程中需要面临的挑战
在介绍崩溃恢复之前,我们需要详细介绍一下日志系统,文件系统能够进行崩溃恢复操作的核心就在于日志系统,当用户将写入文件后,操作系统实际上并没有直接将内容写入到磁盘中,取而代之的是写入日志操作,也就是说,用户并不会直接对磁盘进行写入,同样,在操作系统恢复进程时,会从日志中读取没有持久化到磁盘中的数据,以此来保证之前的文件内容并不会丢失
而日志系统设计过程中,主要需要满足三点特性:
1)原子操作:由于写入日志的内容最后会被同步到磁盘中,因此这一部分文件内容同步时必须满足:要么全部同步成功,要么一点也不同步,保证同步的正确性
2)快速恢复:当操作系统崩溃宕机时,日志系统需要满足操作系统能够快速地从日志中读取内容恢复数据
3)高性能:日志系统需要满足高性能,以应对操作系统中多个进程同时的读写操作,这一点在我们后续介绍中会提到,我们会发现,在xv6中并不能实现高性能这一点,而如今的Ext4文件系统也在尽力向着高性能靠近
xv6中写入文件的操作主要分为以下几步:
1):写入日志,一般来说,写入日志操作很迅速,当用户写入文件内容后,展示出的数据就已经被写入到了日志中
2):提交日志:在提交日志操作中,主要完成将日志的内容同步到缓存中,来保证日志内容与缓存内容的一致性
3):持久化到磁盘:在完成提交日志后,这一步会将缓存中的内容持久化到磁盘中,到了这里才真正地将内容写到了磁盘中,完成了文件内容的写入
4):清除日志:最后会清除日志,使得日志能够进行下一步的读写操作
想要理解上述过程,我们可以由浅入深先来看一看xv6中关于日志操作的源码,在xv6中,每一个信息主要保存在xv6文件结构中的inode结点中,而每次写入数据时,需要新分配一个inode节点进行存储,也就是下面的ialloc函数:
在这个函数中,主要完成了分配指定数量的inode节点块的操作,如果发现当前inode节点为空,说明是一个空闲节点,那么就可以写入,而这里的log_write就是写入日志操作,因此写入内容时,内容会首先被保存在日志log中
在写入文件函数syswrite中,将日志内容同步到缓存之前会开启事务begin_op(),在日志内容同步结束后会关闭事务end_op(),通过事务保证了缓存内容要么被完全同步,要么一点不同步,体现了日志的原子性操作:
而在日志内容完全同步到缓存后,会调用end_op()函数,完成对于事务的提交:
在这里,会判断日志的变量log.outstanding,这个变量的含义为系统外部正在使用当前日志的进程个数,只有当没有进程使用该log文件时,才会进行提交操作
在最后的commit函数中,会将最后对于日志的更改进行同步,之后先写入日志头的信息到磁盘中,再调用install_trans()函数将缓存的内容写入到磁盘中:
直到这里,xv6操作系统才彻底完成了对于文件内容的写入,我们可以发现,在xv6中,对于一个文件的写入要进行两次拷贝(日志->缓存 缓存->磁盘),而这两次拷贝是十分耗费性能的,那么我们为什么不将内容直接写入到缓存中呢,这样仅仅需要一次拷贝就可以了
答案肯定是不行的,如果直接写入到缓存中,操作系统宕机会清除所有的缓存,这时之前的文件内容会全部丢失,因此引入日志的好处与核心就在于,它支持通过原子性操作满足文件系统的正确性,而在写入文件操作的四个过程中,无论哪个过程之间发生崩溃都不会对文件内容产生影响:
虽然xv6文件系统能够满足基本的崩溃恢复操作,保证文件内容的正确性,但是通过对于大致写入文件流程我们也可以看出,xv6对于文件内容的写入是异常笨拙且缓慢的,它每次写入文件都需要经过两次拷贝完成,同时由于事务的原子性,即使有多个事务到达,xv6也必须依次执行每个事务,导致效率缓慢,在后续的Ext3文件系统中,对于高性能提出了一系列解决方案
限于篇幅原因,后续关于Ext3文件系统的介绍笔者会再写一篇文章进行讲述的,希望对你有所帮助!!!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。