【问题标题】:forks and pipes, what am I doing wrong?叉子和管道,我做错了什么?
【发布时间】:2020-02-11 12:31:37
【问题描述】:

我正在尝试了解管道和重定向。为此,我正在做一些小程序来习惯相关的系统调用。在这一个上,我试图在文件 pipe4.c 上启动 cat,并将其输出通过管道传输到我之后启动的 grep。它不起作用,我不明白结果, 我虽然逻辑很好,但我显然错过了叉子的一些东西。我做错了什么?

代码如下:

    #include <stdio.h>
    #include <fcntl.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #define BUFF_SIZE 4092

    //redirecting the output of a program ('cat' here)
    //to the stdin of another program ('grep' here)
    void    err_handler(char *msg)
    {
        perror(msg);
        exit(EXIT_FAILURE);
    }

    int main(void)
    {
        //creating a pipe to communicate between the child processes
        int p[2];
        if (pipe(p) < 0)
            err_handler("pipe error: ");
        /*
        ** forking for cat
        */
        pid_t cat_pid;
        if ((cat_pid = fork()) < 0)
            err_handler("fork error: ");
        if (cat_pid)
            close(p[1]);
        if (!cat_pid) {
            printf("===CAT===\n");
            dup2(p[1], STDOUT_FILENO);
            close(p[0]);
            close(p[1]);
            execl("/bin/cat", "cat", "pipe4.c", NULL);
            exit(EXIT_SUCCESS);
        }
        /*
        ** forking for grep
        */
        pid_t grep_pid;
        if ((grep_pid = fork()) < 0)
            err_handler("fork_error: ");
        if (grep_pid)
            wait(&grep_pid);
        if (!grep_pid) {
            printf("===GREP===\n");
            dup2(p[0], STDIN_FILENO);
            close(p[0]);
            close(p[1]);
            execl("/bin/grep", "grep", "\"err_handler\"", NULL);
            exit(EXIT_SUCCESS);
        }
        return 0;

}

我只在我的终端上得到这个:

> pom@parrot ~/dev/19/syscall> sudo ./a.out 
> ===GREP===
> ===CAT===
> ===GREP===

每次执行时,这些行的打印顺序都会发生变化。 我所期望的显然是我的 pipe4.c 文件中包含“err_handler”的所有行,就像我直接在 shell 中那样:

> pom@parrot ~/dev/19/syscall> cat pipe4.c | grep "err_handler"
> void  err_handler(char *msg)      err_handler("pipe error: ");
>       err_handler("fork error: ");            err_handler("creat error: ");
>               err_handler("read error: ");
>               err_handler("write error:");

【问题讨论】:

  • 为什么父母在等待cat?如果数据流很大,cat 会阻塞写入,grep 将永远不会被执行。您应该在等待之前同时执行 grep 和 cat。
  • 感谢您的建议,我已将其删除。但这并不能解决我的问题。我只得到'printf',所以问题可能出在管道上?
  • 你没有正确使用wait函数。
  • 正如我所说,我删除了等待,我还缺少什么?
  • 如果您能准确解释“不起作用”的含义以及您看到的结果,将会有所帮助。进程是否以意外结果终止,是否挂起,是否存在段错误? “不起作用”并不是对问题的特别好的描述。

标签: c unix pipe fork system-calls


【解决方案1】:

有(我认为!)3 个主要问题。

1) 您没有正确使用等待。我建议改用 waitpid。

2) 至少在我的系统上,/bin/grep 不存在。它是 /usr/bin/grep。但是,由于您在exec 失败时返回 EXIT_SUCCESS,因此您没有看到错误。你应该用execl(...); perror("execl"); exit(EXIT_FAILURE);替换execl (...); exit(EXIT_SUCCESS)

3) 您正在搜索文字引号。就好像你跑了:

grep '"err_handler"'

也就是说,生成 grep 时 execl 的参数应该是 "err_handler",而不是 "\"err_handler\""

【讨论】:

  • 谢谢,第三点是问题所在。我虽然通过转义引号相当于在终端中编写 [grep "err_handler"] 。是的,我使用的是 wait(),但打算“做”一个 waitpid(),感谢您指出这一点。 grep 在我的系统中的 /bin/ 中!
猜你喜欢
  • 2015-11-08
  • 1970-01-01
  • 1970-01-01
  • 2021-04-13
  • 2023-04-01
  • 1970-01-01
  • 2015-07-15
  • 1970-01-01
  • 2014-02-16
相关资源
最近更新 更多