c++ - 在删除文件之前检查文件是否仍在被另一个进程使用(c、c++、linux)

标签 c++ c linux file

当其他进程(它来自我在我的 c++ 代码中使用 <file.txt> 调用的另一个程序)完成使用它时,我需要删除一个文件(假设它被命名为 system("anotherProgram <file.txt>") )。
我的程序生成 <file.txt> ,将其传递给外部应用程序。
该应用程序将其步骤写入日志文件,并且该应用程序所有者说在日志文件中打印了一些消息(例如 'aaa' )后应用程序不需要该文件。
我想外部应用程序只是解析 <file.txt>完成后打印消息 'aaa'在日志中。所以,我相信在那之后,删除 <file.txt> 应该是安全的。在我的代码中。
因此,在我的代码中,我正在检查日志文件,当我看到消息 'aaa' 时,我让我的进程休眠 1000 毫秒,然后删除文件。
但在某些情况下,我仍然从该外部应用程序中收到错误,它无法找到 <file.txt>。文件,所以我猜即使在消息 'aaa' 之后打印在日志中,应用程序仍然尝试使用 <file.txt> .
我想知道我在这里是否做错了什么。
PS:如果我要睡更长时间(比如 10000 毫秒),我不会遇到这个问题。

最佳答案

明智的做法是通过文件描述符(通常是标准输入)传递文件。
(大多数程序都支持从标准输入读取它们的输入,但如果那个特定的不支持,您仍然可以使用 /proc/self/fd/N 作为文件描述符 N。)
而不是使用 system() ,你 fork 一个子进程,并让它执行所需的二进制或 shell 命令。我已经展示了一个合适的函数here .
在父进程中,您只需使用 /proc/self/fd/N对于文件名,并且在执行子进程之前不要关闭文件。您可以取消链接(删除)该文件,因为只要至少有一个进程将其打开,底层 inode(文件元数据和内容)就可以访问。
所以,这是我将使用的方案:

  • 打开并创建目标文件(使用 O_CREAT | O_RDWRO_CREAT | O_EXCL | O_RDWR ,或者如果使用 stdio,则 ww+ )。
  • 如果在不再需要时应该删除该文件,请立即取消链接。
  • 创建文件内容。
  • 如果使用 stdio,我们只想保留文件描述符,但关闭流:
    int fd = dup(fileno(handle));
    fclose(handle);
    
    否则,我们将假设 fd是目标文件的文件描述符。
  • lseek(newfd, 0, SEEK_SET);所以描述符所指描述的文件位置在文件的开头。
  • 使用一个小的缓冲区,比如 32 个字符,通过 snprintf(buffer, sizeof buffer, "/proc/self/fd/%d", fd); 打印文件描述符(在子进程中)的路径到
  • 构造程序参数对应的字符串数组,[0]为程序名,[1]为第一个参数,以此类推;与 (char *)0作为最终参数。使用前面提到的 buffer为文件名。
  • 调用 pid = run(binary, argarray); , 其中 argarray是前面提到的字符串数组,binary是要运行的二进制文件的名称(如果在以 PATH 命名的目录中),或其完整路径。 (如果它包含斜线,则解释为绝对或相对路径;如果不包含,则使用 PATH 环境变量中指定的目录。)
  • 如果 pid == -1 ,该命令无法执行;原因在strerror(errno) .否则,命令将同时运行。
  • 如果您想等到其他程序完成,请调用 reap(pid, NULL) , 或 reap(pid, &status)如果您想了解其退出的详细信息,请查看 int status (但请记住使用 WIFEXITED(status)WEXITSTATUS(status) 等,如 man 2 waitpid 中所述。

  • 由于文件的自动删除是预先处理的,如果父进程之后无事可做,而不是派生一个子进程,您可以简单地用新进程替换当前进程,只使用 execv(binary, argarray)execvp(binary, argarray) ,取决于是否 binary是要执行的程序二进制/脚本的路径或名称。

    关于c++ - 在删除文件之前检查文件是否仍在被另一个进程使用(c、c++、linux),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63299821/

    相关文章:

    c - 调用 printf() 的具有未定义参数编号的函数

    linux - 在linux task scheduler中,周期性调用什么函数来做调度工作?

    linux - 如何获取 Yocto 中所有可用目标的列表?

    c++ - 使用作为对 vector 元素的引用的参数调用 c++ 函数

    c++ - 将字符串转换为 const *json 后,在传递 json 对象时,显示失败 : (IsObject()), 如何解决?

    c - 夹板和测试覆盖率分析?

    c - 加载共享库的两个实例

    C++ 销毁顺序 : Calling a field destructor before the class destructor

    c++ - SDL TextInput(使用新的 1.3 结构)

    c - 双指针地址加法问题