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

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

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

Solutions Collecting From Web of "为什么在UNIX中删除后可以访问文件?"

你基本上有2或3个不相关的问题。 文本编辑器喜欢在编辑会话开始时将整个文件读入内存。 试想一下,你输入的每一个字符都被立即保存到磁盘上,其后的所有字符都被重写了一个地方,以便腾出空间。 那太糟糕了。 更好的是,你实际编辑的东西是文件的内存表示(指向行的指针数组,可能附带有一些元数据),只有当你显式地保存时才会被转换回线性流。

任何相对较新版本的vim都会通知您,如果正在编辑的文件是从其原始位置删除的

 E211: File "filename" no longer available 

这个警告不仅适用于unix。 Windows上的gvim会给你,如果你删除正在编辑的文件。 它提醒您,如果您不想让文件消失,则需要在退出之前保存正在处理的版本。

(注意:这个警告不会立即出现,vim只会在离开它之后才会将原始文件存回前台。)

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

问题2,为什么一些Windows编辑保持文件打开和锁定 – 我不知道,Windows的人是疯了。

问题3,实际上是关于unix的,为什么打开的文件在被删除后仍然可以访问 – 这是最有趣的一个。 答案,保证直接提交时震惊你:

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

系统调用unlink可能会出现删除文件的基础rm和任何其他命令。 它被称为unlink ,而不是remove或删除文件或类似的东西,因为它不会删除文件。 它删除一个链接 (aka目录项),它是目录中文件和名称之间的关联。 (注意:ANSI C增加了remove作为一个更通用的函数来安抚非unix人员,他们并不打算实现unix文件系统的语义,但是在unix上,如果目标是一个目录, remove就是一个rmdir ,并且unlink其他所有的连接。 )

一个文件可以有多个链接(请参阅ln命令以了解它们是如何创建的),这意味着同一个文件被多个名称所知。 如果你是其中的一个,其他人就留在这里,文件不会被删除。 当你删除最后一个链接会发生什么? 那么,现在你有一个没有名字的文件。 但名称只是对文件的一种引用。 至少有2个其他文件描述符和mmap区域。 当文件的最后一个引用消失时,即文件被删除。

由于引用有多种形式,因此会导致文件被删除的事件种类很多。 这里有些例子:

  • 取消链接(RM等)
  • 关闭文件描述符
    • dup2(可以隐式关闭一个文件描述符,然后用另一个文件描述符的副本替换)
    • exec(可以通过关闭执行标志来关闭文件描述符)
  • munmap(取消映射内存区域)
    • mmap(如果您在已映射的地址上创建新的内存映射,则旧映射将不映射)
  • 进程死亡(关闭所有文件描述符并取消映射进程的所有内存映射)
    • 正常退出
    • 内核产生的致命信号(^ C,segfault)
    • 从另一个进程发送的致命信号(kill)

我不会说这个完整的名单。 我不鼓励任何人尝试建立一个完整的清单。 只要知道rm是“删除名称”,而不是“删除文件”,并且文件一旦没有被使用就立即消失。

如果要立即销毁文件的内容,请截断它。 所有已经使用它的进程都会发现它的大小突然变为0.(这是对正常的文件访问方法的破坏,要彻底销毁它,以至于即使是有原始磁盘访问权限的用户也不能读取过去的内容在那里,你需要覆盖它,有一个工具称为shred 。)

我认为你的问题与Windows / Linux的区别无关。 这是关于VI如何工作的。

当使用VI来编辑文件时。 VI将创建一个.swp文件。 .swp文件就是你实际编辑的内容。 同时,如果其他用户删除原始文件将不会影响您的编辑。 而当你在VI中键入:w时,VI将使用.swp文件来覆盖原始文件。