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

San*_*jay 2 unix linux filesystems file

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

  • 在阅读时我是否需要考虑任何锁定机制,因此没有人能够在阅读时删除相同的文件.

  • 从windows中显示不同行为的原因是什么(如在某些编辑器中打开文件而不是删除该文件时在Windows中)

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

我一般都在询问文件,但是特定于平台,即unix.如果我使用java程序(缓冲读取器)读取文件并在读取时删除文件会发生什么情况,缓冲区读取器是否仍能读取下一个块的文件?

小智 7

那里你基本上有两个或三个不相关的问题.文本编辑器喜欢在编辑会话开始时将整个文件读入内存.想象一下,您键入的每个字符都会立即保存到磁盘,文件中的所有字符都会被重写一个位置,以便腾出空间.那太糟糕了.更实际的是,你实际编辑的是文件的内存表示(指向行的指针数组,可能附带了一些元数据),只有在你明确保存时才会转换回线性流.

任何相对较新版本的vim都会通知您,如果您编辑的文件已从其原始位置删除并带有该消息

E211: File "filename" no longer available
Run Code Online (Sandbox Code Playgroud)

此警告不仅适用于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其中之一,其他人就会四处寻找并且文件不会被删除.删除最后一个链接会发生什么?好吧,现在你有一个没有名字的文件.但名称只是对文件的一种引用.至少还有2个:文件描述符和mmap区域.当文件的最后一个引用消失时,就是删除文件的时候.

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

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

我不会称之为完整清单.我不鼓励任何人试图建立一个完整的清单.只要知道这rm是"删除名称",而不是"删除文件",文件一旦不使用就会消失.

如果要立即销毁文件的内容,请将其截断.已经使用它的所有进程都会发现它的大小突然变为0.(就普通文件访问方法而言,这是破坏性的.要彻底销毁它,以便即使有原始磁盘访问权限的人也无法读取以前的内容在那里,你需要覆盖它.有一个工具要求shred.)