-1

我正在使用 fork-exec 模式编写一些代码,子进程旨在打开 /tmp 目录中的文件(追加创建模式)以将其输出写入。(该文件事先不存在,而是在打开时创建,或者至少应该是......)但是,我发现孩子在执行后无法打开任何文件。它可以在fork之后和exec之前打开/创建一个文件并写入它,但是在exec之后我发现该文件没有被创建。此外,如果我在命令行上运行我正在执行的程序(使用相同的参数),它会创建文件并写入它就好了。只有当它从 exec 开始时,它似乎才有这个问题。我真的不知道如何开始考虑这个问题......如果有人对在哪里寻找线索有建议,我真的很感激!

这是一个粗略的示例 - 请注意,这不是运行的实际代码:) 孩子:

#define MSG "Opened file: "
int main (usual stuff) {
    const char* szTemp = "/tmp/helloworld";
    FILE* temp = fopen(szTemp, "a");
    fwrite(MSG, sizeof(char), strlen(MSG), temp);
    fwrite(szTemp, sizeof(char), strlen(szTemp), temp);
    fwrite("\n", sizeof(char), 1, temp);
    fclose(temp);
    // at this point, I see the file with the normal content when Child is run
    // from the command line, but the file is not created if Child is created
    // by a call to exec
}

家长:

int main(usual stuff) {
    pid_t pid = fork();
    if (0 == pid) {
        // fopen/fwrite works fine if I do it here!
        exec(child-process);
    }
    // parent continues...
}
4

1 回答 1

0

好的,我想通了!这就是发生的事情:在调用 exec 之前接触文件的代码显然运行并做了它应该做的事情。main 启动后立即触及文件的代码没有触及文件,因为它从未运行过。该进程在 exec 和 main 之间死亡!

发生这种情况的方式有很多种,但在我的情况下,这是因为它试图加载共享对象 (.so) 文件(动态链接库的 Linux 风格),但路径不在 LD_LIBRARY_PATH 所以它失败了. (从命令行一切正常,因为我的 LD_LIBRARY_PATH 确实包含了正确的目录,但是我从 fork 开始的进程无法访问该环境......)解决方案是简单地使用 exec 的 evnironment 参数传入LD_LIBRARY_PATH 的正确值,然后子进程可以找到 .so 文件并正常启动。

现在,这就是为什么在这种情况下很难检测到的原因......通常,如果一个进程找不到必要的 .so 当它启动时,它会给你一条消息(我相信在 stderr 上)让你确切知道哪个它找不到的图书馆。我的麻烦是父进程是一个守护进程,所以我关闭了标准输入、标准输出和标准错误。当我分叉时,孩子继承了打开的文件描述符,但由于标准流已关闭,它没有任何地方可以发送其输出。一旦我添加了代码以使子进程将 stdout 和 stderr 发送到文件(这是在 fork 和 exec 之间完成的),我就能够在输出文件中看到错误消息。

不过,我在这里有点幸运,因为(主要)出于不相关的原因,我正在为 stdout/stderr 添加输出......

于 2013-07-29T04:37:05.427 回答