【发布时间】:2011-02-14 20:32:15
【问题描述】:
所以,我有一个 Linux 进程,我试图在其中管理磁带上的一些文件。我有以下代码尝试从磁带上的当前存档中提取文件 catalog.xml 并将其复制到固定位置(最终,我将解析该文件并对结果进行一些处理)。但是,我的代码间歇性地无法正常工作。 tar 命令总是成功,(如果我检查文件系统,我会看到 catalog.xml 文件),但有时我的后续检查以查看文件是否存在会返回 false。我在做一些明显错误的事情吗?似乎我可能在 fork()ed 进程返回和该进程的结果在文件系统上可见之间遇到了竞争条件 - 我需要进行一些调用吗?
pid_t tPid = vfork();
if (0 == tPid)
{
int tChildRet;
tChildRet = execlp("tar", "tar", "-xvf", "/dev/nst0", "-C", "/tmp", "catalog.xml", (char *) 0);
_exit(-1 == tChildRet ? EXIT_FAILURE : EXIT_SUCCESS);
}
else
{
wait(&ret);
}
std::ifstream tCatalogFile("/tmp/catalog.xml");
if (tCatalogFile)
{
cout << "File exists!" << endl;
} else {
cout << "File does not exist!" << endl;
}
我得到“文件存在!”或“文件不存在!”,似乎是随机的。
其他说明: 关于失败案例:
- 如果我执行
stat ("/tmp/catalog.xml"),我会得到 -1 的返回值,并将 errno 设置为 ENOENT。 - tar 命令(使用 -v 标志运行)产生预期的一行输出(“catalog.xml”)
/tmp 是本地 tmpfs 文件系统;磁带机是本地设备。 我在 x86_64 机器上使用 2.6.30.9 Linux 内核和 g++ 4.1.2。
提前致谢!
【问题讨论】:
-
还有其他可能导致打开失败的错误(都取决于正在使用的文件系统)。关于文件系统的更多细节会很好。
-
注意:如果 execlp 工作,那么它将永远不会返回。所以 _exit() 只有在 execlp() 失败时才会被调用。你也没有检查 vfork() 是否真的有效。
标签: c++ file-io filesystems fork-join