![联合挂载文件系统中的文件冲突](https://linux22.com/image/1620507/%E8%81%94%E5%90%88%E6%8C%82%E8%BD%BD%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E6%96%87%E4%BB%B6%E5%86%B2%E7%AA%81.png)
我正在从以下来源阅读有关 Union Mount 文件系统的一些资料:
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.386.8972&rep=rep1&type=pdf
以下是该论文的摘录:
除顶层之外的所有文件系统层都被视为只读。如果打开位于较低层的文件进行读取,则会返回该文件的描述符。如果打开位于较低层的文件进行写入,则内核首先将文件复制到顶层,然后返回引用该文件副本的描述符。结果是该文件有两个副本:较低层中的原始未修改副本和较高层中的文件修改副本。当用户执行目录列表时,较低层中的任何重复名称都将被抑制。
这似乎留下了这样一种可能性:当一个实体(例如容器)拥有该文件的只读版本的描述符时,另一个拥有 RW 访问权限的实体会对该文件进行更改同名文件(即具有相同的名称,但来自不同的层)。这些更改将在第一个实体背后进行,它完全不知道。第一个实体在重新启动之前不会获取这些更改。
我的理解正确吗?
此外,如果两个实体请求 RW 访问权限,并且两个实体都对同名文件进行了更改,会发生什么情况?
答案1
没错。你提出的是一种并发问题。多进程和多用户软件经常会遇到这种情况。数据库和文件系统都实现了复杂的方案来控制这类情况。对于文件系统,答案通常涉及锁定而对于数据库来说,它是事务性的酸(可变且复杂的锁定方案)。
所以你的论文描述的是一个实现“多读单写”锁定的文件系统。许多人可以打开文件进行读取,但任何时候只有一个人可以打开文件进行写入。
当源发生更改时,对读取用户的影响取决于应用。成功保存后,文件更改(大概)会刷新回较低层,因此如果用户查找,更改就在那里。在我使用过的每个操作系统上,程序都必须指定在打开句柄时他们想要对句柄进行何种访问(读/读写),而这些决定将驱动应用程序行为。
一般来说,应用程序将被编码以便:
- 定期轮询文件系统,注意变化,并询问您是否要加载它
- 根本不会注意到变化,除非关闭并重新加载应用程序。
- 或者如果另一个进程具有对文件的句柄(读或读写),则不允许您打开该文件。
因此,虽然文件系统和操作系统处理锁定系统并充当守门人,但实际上是应用程序负责解决您提出的问题。
至于你的第二个问题,这要视情况而定。我没有时间阅读你关于这个我从未听说过的文件系统的论文,但我相信根据你所引用的内容,顶层不能存在两个同名的文件(这就是顶层仅写入约束的全部意义所在),从而阻止第二个用户以写入模式打开文件。你引用的图表支持这一点,因为在 /tmp/src/ 下不能有两个名为 example.file 的不同文件。
在创建句柄时声明访问类型的目的是检查现有锁,并在允许的情况下创建自己的锁,这样就可以在不进行某种合并的情况下保持文档的流通性。请注意,仅仅因为您拥有文件的写权限,并不意味着打开它进行写入就是您打开它的唯一方式。这一切都取决于应用程序。