【问题标题】:How to robustly write to a slow & unreliable NFS如何稳健地写入缓慢且不可靠的 NFS
【发布时间】:2018-01-28 16:56:00
【问题描述】:

我不是 C 方面的专家,我正在寻找一些建议,以使我的程序更加健壮和可靠。只是为了提供一些背景信息:我编写了一个程序来执行一些需要很长时间(大约 20 小时)的科学计算,我正在使用 SLRUM 调度系统和 NFS 挂载文件系统在大型大学 HPC linux 集群上执行该程序。似乎发生的情况是,在 20 小时内的某个时间,与文件系统的连接过时(在整个机器上;独立于我的程序)并且第一次尝试打开和写入文件需要很长时间,这会导致segfault cored dumped 错误,到目前为止我无法精确追踪。下面是一个至少在概念上重现错误的最小文件:程序启动,打开一个文件,一切正常。该程序进行了一些长时间的计算(由 sleep() 模拟),尝试再次打开并写入同一个文件,但它失败了。有哪些约定可以使我的代码更健壮,更可靠地将结果写入文件而不会崩溃?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv) {
    // Declare variables
    FILE *outfile;
    char outname[150] = "result.csv";

    // Open file for writing
    printf("CHECKING if output file '%s' is writable?", outname);
    outfile=fopen(outname, "w");
    if (outfile == NULL) {
        perror("Failed: ");
        exit(EXIT_FAILURE);
    }
    fclose(outfile);
    printf(" PASSED.\n");

    // Do some computation that takes really long (around 19h)
    sleep(3);

    // Open file again and Write results
    printf("Writing results to %s ...", outname);
    outfile=fopen(outname, "w");
    if (outfile == NULL) {
        perror("Failed writing in tabulate_vector_new: ");
        exit(EXIT_FAILURE);
    }
    fprintf( outfile, "This is the important result.\n");
    fclose(outfile);

    printf(" DONE.\n");
    return 0;
}

【问题讨论】:

  • 可能不是问题,但如果文件成功关闭,fclose() 返回0;在解决 I/O 问题时,似乎总是值得检查这些明显的框。
  • 这里有一个秘诀:找一位优秀的网络管理员,激励他/她修复 NFS 问题。重复直到完成。
  • 我看不出您包含的程序会出现段错误的任何原因,除非可执行文件本身位于过时的 NFS 文件系统上。如果您可以在调试器下运行它,请告诉我们错误发生在哪一行。
  • 确实如此。在带有 gcc 的 Linux 上,使用“-g”开关构建和链接,然后在 gdb 下以重现问题的方式运行整个过程。您显示的示例代码在我看来没有任何问题。

标签: c linux file nfs


【解决方案1】:

您的程序由于 NFS 问题而出现段错误似乎很奇怪。我希望它无限期地挂起,而不是崩溃。话虽如此,我建议分叉一个新进程来检查 NFS 挂载是否正常工作。这样,您的重要代码将不会直接参与测试有问题的文件系统。类似以下方法的方法可能有用:

pid_t pid = fork();

if (pid == -1)
{
    // error, failed to fork(). should probably give up now. something is really wrong.
} 
else if (pid > 0)
{
    // if the child exits, it has successfully interacted with the NFS file system
    wait(NULL);
    // proceed with attempting to write important data
}
else 
{
    // we are the child; fork df in order to test the NFS file system
    execlp("df", "df", "/mnt", (char *)NULL)
    // the child has been replaced by df, which will try to statfs(2) /mnt for us
}

这里的一般概念是我们使用df 命令来检查NFS 文件系统(我假设它位于/mnt)是否正常工作。如果它暂时不工作,df 应该挂起,直到它再次开始工作,然后退出,将控制权返回给您的程序。如果您怀疑df 可能永远挂起,您可以通过使用alarm(2) 等待一段时间(可能至少几分钟)来增强我的示例,然后您可以重试运行df。请注意,这可能会导致僵死的df 进程继续存在。

最后,正确的解决方案是尝试获得更可靠的 NFS 服务器,但在你能做到之前,我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-03
    • 2022-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多