C语言中的管道,进程复制,文件描述符拷贝和执行系统调用

4

我正在尝试通过管道将字符串列表传递给子进程,在那里它应该使用execl()通过/bin/cat显示。之前它已经能够工作了,除了管道没有关闭,所以程序一直在等待状态。现在不知道出了什么问题,完全不能工作。有人可以看看我的代码并告诉我我做错了什么,导致str数据没有被子进程的cat显示吗?

int main(int argc, char** argv) {

    char *str[] = {"The", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"};
    int fds[TOTAL_CHILDREN];
    int writeFds;
    int catPID;
    int status;

    FILE * write_to_child;

    //create pipe
    if (pipe(fds) == -1) {
        perror("creating pipe: failed");
        exit(EXIT_FAILURE);
    }
    pipe(fds);
    //create subprocess for cat child

    switch (catPID) {
        case 0: // successful creation of child
            close(fds[1]); //close write side from parents
            close(0); //close stdin
            dup(fds[0]); //connect pipe from execl cat to stdin

            execl("/bin/cat", "cat", (char *) 0);
            perror("exec failed!");
            exit(20);
            break;

        case -1: //failure
            perror("fork failed: cat process");
            exit(EXIT_FAILURE);

        default: //parent process
            close(fds[0]);

            writeFds = fds[1];
            write_to_child = fdopen(fds[1], "w");

            if (write_to_child == NULL) {
                perror("write to pipe failed");
                exit(EXIT_FAILURE);
            }
            break;


    }

    int i;
    for (i = 0; i < 9; i++){
        fprintf(write_to_child, "%s\n", str[i]);
    }

    fclose(write_to_child);
    close(writeFds);

    wait(&status);

    return (EXIT_SUCCESS);
}

请查看此链接:https://dev59.com/GGox5IYBdhLWcg3wIRD3 - qwr
2
如果你要问一个关于 fork() 的问题,那么你应该在程序中调用 fork() - Barmar
谢谢,那是真的! - codeBarer
1
我之前让它工作了...不知道我做了什么,现在完全不工作了。这就是为什么你应该使用版本控制系统(VCS)来管理代码的原因。当某些东西运行得足够好时,你可以保存一个版本,这样你就有一个记录,如果你以后再犯错误,你可以回到那个版本。即使是用于课程的玩具程序,在开发过程中使用VCS也有优势。(我将我的很多SO答案保存在一个git存储库中,如果我需要处理一个棘手的问题,我会创建一个分支,复制并保存原始代码,然后开始我的答案。) - Jonathan Leffler
参见C系统调用pipe()fork()exec() - 同一作者。也与如何循环遍历stdin管道输出到子进程 - execl()命令在C中非常相似 - 不同的作者。 - Jonathan Leffler
@user2250263 请查看此链接http://stackoverflow.com/posts/16497153/edit。这是昨天提出的类似问题,但我当时回答得比较简短。现在我已经发布了完整的答案。它可能对您也有帮助。 - qwr
1个回答

3
您可能想要添加这行代码。
catPID = fork();

我不确定为什么你两次使用了 pipe(fds)

,这可能造成混淆。


你像忍者一样调试!非常感谢。我不知道自己在做什么,但我删除了 fork 并复制了 pipe。你知道我可以用哪些资源来参考这些系统调用吗?现在你已经解决了我的问题,我想要从 cat 中读取所有值到 sort。我猜我需要从第一个子进程创建一个管道到另一个 fork() 的子进程? - codeBarer
1
man命令通常用于查看第2节中的系统调用,这是非常有用的。你可以使用另一个管道来处理数据,但为什么不直接将cat替换为sort呢?因为cat只是简单地复制标准输入到标准输出。 - parkydr
这就是我所做的,我用sort替换了cat,但在获取排序值后,我必须删除重复单词。 - codeBarer
sort -u 将会移除重复项。 - parkydr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接