当前位置: 首页 > 面试题库 >

在Unix中删除后为什么可以访问文件?

翟嘉志
2023-03-14
问题内容

我想到了一个并发问题( 在Solaris中 ),如果在读取某人时尝试删除同一文件会发生什么。我有一个关于 Solaris / Linux中
文件存在的查询。假设我有一个文件test.txt,已经在vi编辑器中将其 打开 ,然后打开了一个重复的会话并 删除了
该文件,但是即使删除了该文件,我仍然可以读取该文件。所以这是我的问题:

  • 我在读取时是否需要考虑任何 锁定 机制,所以没有人能够在读取时删除同一文件。

  • 显示与Windows不同行为的原因是什么(例如在Windows中,如果文件在某些​​编辑器中打开而不是我们无法删除该文件)

  • 删除该文件后,如果我还没有从vi编辑器中关闭文件,我仍然能够读取该文件。

我问的文件一般,但是是平台特定的,即 unix
。如果我使用Java程序(缓冲区读取器)读取文件,并且在读取时删除了文件,缓冲区读取器是否仍然能够读取下一个块的文件会发生什么?


问题答案:

那里基本上有2或3个无关的问题。文本编辑器喜欢在编辑会话开始时将整个文件读入内存。想象一下,您键入的每个字符都会立即保存到磁盘中,文件中的所有字符都将被重写一处,以腾出空间。那太可怕了。更好的是,您实际上正在编辑的是文件的内存表示形式(指向行的指针的数组,可能附加了一些元数据),只有在您明确保存时,它才会转换回线性流。

如果您正在编辑的文件从其原始位置被删除,则任何相对较新版本的vim都会通知您,并显示以下消息

E211: File "filename" no longer available

此警告不仅针对Unix。如果您删除正在编辑的文件,Windows上的gvim会为您提供。它提醒您,如果您不想丢失文件,则需要在退出之前保存正在处理的版本。

(注意:警告不会立即出现-vim仅在离开原始文件后将其放回前台时才检查原始文件的存在。)

这就是问题1,文本编辑器的行为-没有理由让他们在整个会话中保持文件打开状态,因为除了启动和保存操作外,他们实际上并没有使用它。

问题2,为什么某些Windows编辑器会保持文件打开和锁定状态?我不知道,Windows人士对此感到很困惑。

问题3,实际上是关于unix的问题,为什么打开的文件在删除后仍可访问-这是最有趣的一个。答案,当直接出现时一定会让您震惊:

没有命令,函数,系统调用或其他任何实际要求删除文件的方法。

rm系统调用包括底层和删除文件的任何其他命令unlink。它被称为unlink,不是removedeletefile或类似名称,因为它不会删除文件。它删除一个
链接 (又名目录条目),该 链接 是文件和目录中名称之间的关联。(注:ANSI C
remove作为更通用的功能添加,可以安抚那些无意实现unix文件系统语义的非unix人,但是在unix上,remove这只是rmdir目标是目录以及unlink其他所有目的而已。)

一个文件可以具有多个链接(有关ln创建方式,请参见命令),这意味着同一文件可以被多个名称识别。如果您是rm其中之一,则其他人会留下来,并且不会删除文件。删除最后一个链接会怎样?好了,现在您有了一个没有名称的文件。但是名称只是对文件的一种引用。至少还有两个:文件描述符和mmap区域。当最后一个文件
引用 消失时,即删除该文件。

由于引用以多种形式出现,因此有多种事件可以导致文件被删除。这里有些例子:

  • 取消链接(rm等)
  • 关闭文件描述符
    • dup2(可以在将文件描述符替换为其他文件描述符的副本之前隐式关闭文件描述符)
    • exec(可以通过close-on-exec标志关闭文件描述符)
  • munmap(取消映射内存区域)
    • mmap(如果在已经映射的地址上创建新的内存映射,则旧映射将不被映射)
  • 进程终止(关闭所有文件描述符并取消映射进程的所有内存映射)
    • 正常出口
    • 内核生成的致命信号(^ C,segfault)
    • 从另一个进程发送的致命信号(杀死)

我不会称其为完整清单。而且我不鼓励任何人尝试构建完整列表。只需知道这rm是“删除名称”,而不是“删除文件”,并且文件在不使用时就会消失。

如果要立即销毁文件的内容,请截断它。已经使用它的所有进程都会发现它的大小突然变为0。(就普通的文件访问方法而言,这是销毁。要更彻底地销毁它,以至于即使具有原始磁盘访问权限的人也无法读取过去的内容。在那里,您需要覆盖它。有一个shred用于此的工具。)



 类似资料:
  • 本文向大家介绍react中可以在render访问refs吗?为什么?相关面试题,主要包含被问及react中可以在render访问refs吗?为什么?时的应答技巧和注意事项,需要的朋友参考一下 不可以,render 阶段 DOM 还没有生成,无法获取 DOM。DOM 的获取需要在 pre-commit 阶段和 commit 阶段

  • 问题内容: 我只是编写了一个示例程序来查看 删除此文件* 的行为 * 问题 在fun()中执行 删除操作 后,如何在fun()中使用此指针访问func_2()? 现在主要在删除该指针时如何执行 obj- > fun_2? 如果在杀死该对象后能够访问函数成员,那么为什么数据成员的数据为零‘0’? m使用linux ubuntu和g ++编译器 问题答案: 让我们将其与类似的szenario进行比较:

  • 使用 degit 下载了一些文件,删除时总是提示需要管理员权限,但是问题是我就是管理员,试了一些网上的方法,也是通通无效,最后试了一下 rimraf 就可以直接删除,这是怎么做到的?

  • 代码“起作用”,因为它返回预期的信息(DemoPOJO对象列表)。但是,如下所示的控制台输出所示,正在对localhost上的REST服务进行两次调用:8080/v2/demopojo。我有一种感觉,第二次调用是对反应编程缺乏了解的结果,但我不知道第二次调用是在这个REST API上进行的,我想消除它,因为当部署“实际的东西”时,冗余很可能是一个性能问题。 在提供的代码中,在localhost:8

  • 问题内容: 说我有一些任意的多行文本文件: 如何在不使文本文件无效的情况下仅删除文件的最后一个字符(e,而不是换行符或null)? 问题答案: 一个更简单的方法( 输出到stdout ,不更新输入文件): 是仅与最后一个输入行匹配的Sed地址,因此导致仅在最后一行执行以下函数调用()。 用空字符串替换(在本例中为 last )行的 最后 一个字符;即,有效地删除最后一个字符。(在换行符之前)。 匹

  • 问题内容: 请考虑以下情形: 在我看来,在VS2005中,在“擦除”之后,迭代器将等于end(),因此在尝试增加它时会崩溃。此处介绍的行为之间,编译器之间是否真的存在差异?如果是这样,“擦除”之后的迭代器等于UNIX / Linux中的什么? 谢谢… 问题答案: 是的,如果您删除一个迭代器,则该迭代器将获得所谓的 singular value ,这意味着它不再属于任何容器。您不能再递增,递减或读出