首页 > 解决方案 > 是否可以暂时隐藏 linux 中任何系统调用的文件?

问题描述

我正在尝试使用 FUSE 实现文件系统,并且我希望文件在被删除时暂时隐藏。我试图将所有文件的名称或其 inode 存储在一个数组中,并在调用诸如 'open' 、 'getattr' 或 'readdir' 之类的系统调用时检查它们。但是当这个数字变得非常巨大时,它可能会消耗大量的性能。所以我想知道有没有更好的方法来做到这一点?提前致谢!

标签: clinuxfilesystemsfuse

解决方案


您的方法存在两个问题(以及 Oren Kishon 指出的解决方案,并标记为已选中):

  • 首先是文件本身没有名称。文件名不是文件的一部分。文件名到文件(实际上是到 inode)的映射是由系统为用户的商品而创建的,但名称完全独立于它们指向的文件。这意味着您很容易知道链接指向哪个inode,但很难进行反向映射(获取指向inode的目录条目,只需知道inode)删除文件是两个相过程。在第一阶段,您调用unlink(2)系统调用从它所属的目录中删除一个链接(删除一个目录条目),然后释放与该文件有关的所有块,但前提是引用计数(存储在inode 本身)下降到零。 这是一个简单的过程,因为一切都从您要删除的目录条目开始。但是,如果您不删除它,那么稍后搜索它会很痛苦,如下所示,在此处说明的第二个问题中。
  • 其次,如果您使用六个链接(硬链接)到同一个文件进行此操作,您将永远不知道何时需要将空间实际重新分配给另一个文件(因为您用完了未分配的空间)因为inode上的链接引用计数仍然是6。更糟糕的是,如果您在 inode 中添加第二个 ref 计数以跟踪尚未分配的真正已擦除文件的(不同)数量,那么问题是您必须搜索整个文件系统。(因为您不知道关于链接应该在哪里)因此您需要维护大量信息(以添加文件在文件系统中占用的空间)首先收集所有指向该文件的链接,然后检查这是否确实必须释放的文件,以防文件系统中需要更多空间。

顺便说一句,您的问题在用户空间中有一个简单的解决方案。只需修改rm命令以从不完全擦除文件(例如,永远不要取消链接到文件的最后一个链接),而是将文件移动到文件所在的同一文件系统中某个固定目录中的队列中,以处理最后一个链接到它,这将保留仍然分配的文件(但是您会丢失任何引用,或者您可以将其保存在关联文件中,以文件名命名)。监控进程可以检查可用空间量并从队列中选择第一个(最旧的擦除),并真正擦除它。请注意,如果您擦除了大文件,这将使您的系统负载在实际擦除您正在释放的文件时随机增长。

还有另一种选择。使用zfs作为您的文件系统。这需要大量的内存和cpu,但是对于取消删除文件是一个完整的解决方案,因为zfs保存了文件系统的完整历史,所以你可以及时回到文件存在的快照,然后制作一个它的副本,实际上是在恢复它。ZFS 可以在 WORM(一次写入多次读取,作为 DVD)媒体上使用,这允许您随着时间的推移保存文件系统状态(以不再重复使用相同数据为代价)但是您永远不会丢失文件。

编辑

在一种情况下,文件不再可用于任何其他进程,而不是打开它的进程。在这种情况下,一个进程打开一个文件,然后将其删除(删除只涉及断开允许将文件名转换为系统中的 inode 的链接)但继续使用该文件,直到它最终关闭。

您可能知道,一个文件可以同时被多个文件打开。除了磁盘 inode 中的引用数量外,内核内存中的 inode 表中还有许多对 inode 的引用。这是磁盘 inode 中文件的引用数(指向文件 inode 的目录条目数)加上每个文件条目的引用,表明文件已打开。

当一个文件被取消链接(并且应该被删除,因为没有更多指向 inode 的链接正在引用它)时,释放不会立即进行,因为该文件仍在被进程使用。该文件是活动的,尽管它没有出现在文件系统中(在任何目录中都没有对它的引用)只有当文件的最后一个close(2)发生时,文件才会在系统中被释放。

但是引用该文件的目录条目发生了什么。它可以立即被重用(正如我在其中一条评论中告诉你的)它被释放,早在文件被释放之前。将创建一个新文件(它将强制成为不同的 inode,因为旧的 inode 仍在使用中)并将其命名为原始文件(因为您决定将其命名为相同),这没有问题,但是您正在使用不同的文件。旧文件仍在使用中,并且没有名称,因此除了使用它的进程之外,其他进程不可见。这种技术经常用于使用临时文件,您可以在其中创建一个文件open(2),然后立即使用unlink(2)它。没有其他进程可以访问该文件,并且该文件将在文件条目被释放后立即被释放close(2)d。但是这样的文件将在最后一个close(2)被调用时被释放。没有这种特征的文件可以在系统重新启动后继续存在。(它甚至无法在打开它的过程中存活)

正如问题所述:

是否可以暂时隐藏 linux 中任何系统调用的文件?

该文件对所有需要文件名称的系统调用隐藏(它不再有名称),但对其他系统调用不隐藏(例如fstat(2),继续工作,但stat(2)无法在该文件上使用,与link(2), rename(2), open(2),相同ETC。)


推荐阅读