2013-10-18 41 views
3

在我的程序(在Mac OS X上)中,我使用以下代码打开了该文件。打开读取和写入的文件可以取消关联

int fd; 
fd = open(filename, O_RDWR); 

计划要删除的文件如下:

unlink(filename); 

在我的情况,我有被打开,删除相同的文件。我观察到以下内容:

  1. 打开文件后,我可以使用此程序甚至通过使用rm命令将其删除。
  2. 删除文件后,读取和写入操作对文件没有任何问题。

我想知道背后的原因。如何防止rm命令或unlink(2)系统调用删除正在打开的文件?

+1

打开这不就是'取消链接的预期行为(2)'?你检查过文件吗? “如果 一个或多个进程在最后一个链接被删除时打开文件,链接将被删除,但文件的删除将被延迟,直到所有对该文件的引用都被关闭。” –

+0

@CarlNorum:我检查了取消链接(2)。这是预期的行为。但是为什么unlink(2)之后的读写操作成功了? – doptimusprime

+0

就像文档说的那样,文件在引用关闭之前不会被删除。该文件仍然存在,所以'read'和'write'应该继续工作,对吧? –

回答

1

这是UNIX系统中的正常情况。当你rm或取消链接一个打开的文件。 UNIX系统只是标记一个标志,并不会真正删除该文件的欺骗。直到文件关闭。它会在文件系统中真正删除。

它可以帮助守护进程正常工作。

+0

感谢您提供推理。如何防止'unlink(2)'和'rm'删除打开的文件? – doptimusprime

+1

使用chmod和chown限制用户和组写入文件 – Chair

6

您不能阻止unlink(2)取消链接有权取消链接的文件(即,它具有对目录的写入访问权限)。

unlink不叫unlink因为没有人能想到一个更好的名字。这就是所谓的,因为它就是这样做的;它将该文件从目录中取消链接。 (一个目录只是一个链接集合,即它将名称与相应数据的位置关联起来。)它不会删除文件;当文件系统不再有任何链接时,该文件将被文件系统垃圾收集。

打开文件描述符不是保持文件链接的唯一方法。另一种很常见的方法是使用link(1)命令,而不使用-s选项。这会创建“硬”链接。如果一个文件有多个硬链接,那么删除其中一个链接(使用unlink(2))就是这样 - 它删除了其中一个链接。

rm命令有一个可能更令人困惑的名字,但它也只删除,而不是文件。只要有人链接到该文件,该文件就存在,包括正在运行的进程。

+0

+1,但建议进行小的编辑。在最后一段中,将“删除文件的名称”更改为“删除文件的一个名称”(或类似的东西)。这应该有助于说明路径名不是文件,并且任何给定的文件可能有多个指向它的路径。 (很难避免使用“link”而不是“refer”这个词,不清楚哪一个更清楚。) –

+0

@WilliamPursell:够公平的。小编辑。 – rici

3

首先,rm命令调用unlink(2)

然后,断开链接打开的文件是做在Linux或其它Unix系统(例如MacOSX的)是很正常的事情。这是获取临时文件的规范方式(如tmpfile(3)可能)。

您应该了解inodes是什么,并意识到文件不是它的名称或文件路径,而是本质上是一个inode。一个文件可以包含零个,一个或多个文件路径或名称(如果所有名称都位于同一文件系统中,则可以使用系统调用添加更多内容)。目录条目将名称与inode关联。

因此没有(POSIX便携式)禁止没有任何名称的打开ed文件的I/O。 对于某些打开的文件,内核有其参考计数器到其inode,并保持该inode,直到所有进程open(2) - 它做了close(2)它或已终止。

1

A 链接是一个与某个文件关联的名称(一个文件基本上是unamed)。请注意,文件可能具有不同的名称(请尝试ln)。

unlink()将此关联之一移除到文件。如果您删除了文件的最后一个链接,这只会使您无法通过名称访问该文件。 但是,这并不意味着该文件是不可用的,因为文件可能已被打开,并且他目前正被某些应用程序读取/写入。

一个文件,当且仅当删除: - 有它 没有联系 - 它目前不被任何应用程序