是否可以在 Linux 中的任何系统调用中临时隐藏文件? 编辑

如何解决是否可以在 Linux 中的任何系统调用中临时隐藏文件? 编辑

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

解决方法

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

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

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

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

编辑

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

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

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

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

正如问题所述:

是否可以在 Linux 中的任何系统调用中临时隐藏文件?

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

,

如果我理解,当调用 unlink 时,您希望将文件标记为已删除而不是实际删除。 您可以将此标记实现为扩展属性,该属性具有“系统”命名空间(参见 https://man7.org/linux/man-pages/man7/xattr.7.html),该属性未作为文件 xattr 列表的一部分列出。 在您的“取消链接”中,执行 setxattr(system.markdelete)。在您使用路径 arg 的所有其他调用中,以及在 readdir 中,getxattr 并将其视为已删除。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)> insert overwrite table dwd_trade_cart_add_inc > select data.id, > data.user_id, > data.course_id, > date_format(
错误1 hive (edu)> insert into huanhuan values(1,'haoge'); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive> show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 <configuration> <property> <name>yarn.nodemanager.res