【问题标题】:How to check if a file still exists using a file descriptor如何使用文件描述符检查文件是否仍然存在
【发布时间】:2013-03-10 17:39:51
【问题描述】:

我有一个文件描述符,它通过 open() 函数的结果设置为正值,所以这个 fd 表示一个文件。当我删除实际文件 fd 仍然是一个正整数。我想知道如果我出于某种原因删除了一个文件,我怎么知道这个文件描述符不再有效。简而言之,我怎么知道 fd 指示的文件是否仍然存在。我正在尝试在 FreeBSD 上的 C 中执行此操作。

【问题讨论】:

  • 尝试写入或读取文件。这应该会返回一个错误。
  • @RedX 这不是 UNIX 的工作方式。
  • 是的,我知道我必须读取或打开该文件,但有没有办法只用 fd 打开或读取文件?是否有一个只用 fd 读取或打开的 io 函数,没有路径或 FILE*
  • @HasanBozok - 你不能 open 带有 fd 的文件 - 打开 返回 fd。它只是一个 int。
  • 如果您在/p/a/t/h 上获得文件描述符,然后取消链接/p/a/t/h,但/p/a/t/h/2 是指向同一文件的链接,您想要什么行为?

标签: c unix freebsd file-descriptor


【解决方案1】:

Unix 系统允许您删除打开的文件(或者更确切地说,从文件系统中删除对该文件的所有引用)。但文件描述符仍然有效。任何读取和写入调用都将成功,因为它们仍然存在文件名。

换句话说,在文件描述符关闭之前,您无法完全删除文件。关闭后,文件将自动删除。

使用有效的文件描述符,您可以检查文件名是否仍然存在,例如

printf("%d\n", buf.st_nlink);  // 0 means no filenames

其中bufstruct stat,用fstat 初始化。

【讨论】:

  • 感谢您的建议,但这是我面临的不同情况。我只需要检查 fd 指示的文件是否仍然存在。如果不是,那么通过 fd 学习的方法是什么?
  • @HasanBozok - 您可以在有效文件描述符上使用fstat 来获取硬链接的数量。如果为 0,则文件名已被删除。
  • @teppic,有什么方法可以使用ioctl 来实际删除文件吗?如果可以,那会很危险吗?
  • @AnishRam - 内核控制它 - 删除文件的唯一方法是如果没有现有的硬链接,并且 inode 上没有打开的文件描述符。
  • @AnishRam 否。如果要删除文件,请关闭()描述符。 (所有引用该文件的描述符都需要在内核将其删除之前关闭。)
【解决方案2】:

在写入文件之前,您可以使用 access() 检查它是否仍然存在

if (access("/yourfile",W_OK)!=-1) {
    //Write on the file
}

你也可以对描述符做 fstat:

struct stat statbuf;
fstat(fd,&statbuf);
if (statbuf.st_nlink > 0) {
    //File still exists
}

但它会大大降低您的软件速度,并且某些程序可能会将文件链接到其他位置并取消链接原始名称,因此该文件仍然存在但使用不同的名称/位置,并且这种方法不会检测到。

更好的选择是在 GNU/Linux 上使用 inotify,或者在 bsd 上使用 kqueue,但我从未使用过第二个。

您可以使用这些 API 来观察目录的变化,并从内核获取通知,并在您的文件被其他进程删除时获取事件,并对其进行处理。

请记住,此事件不是实时的,因此您仍然可以在获取事件之前使用该文件几毫秒。

【讨论】:

    猜你喜欢
    • 2012-09-02
    • 1970-01-01
    • 2021-05-08
    • 2013-11-08
    • 2010-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    相关资源
    最近更新 更多