Fork-exec 管道重定向问题

发布于 2024-12-22 01:52:13 字数 3490 浏览 2 评论 0原文

谁能告诉我这段代码有什么问题吗?

总之,它创建输入和输出管道以及 fork-exec 的 sort 程序。父级读取字典 /usr/share/dict/words 并将其写入通过 dup2()'d to sort' 的管道s 标准输入,同样,读取它的输出,将其打印到终端(父级的标准输出)。或者,至少,这就是应该发生的事情。

回溯表明父进程挂在第 130 行的 read() 处(用注释“XXX”标记)。几乎就像 sort 不知道文件结尾,但关闭 pipeIn 的写入端应该“发出信号”,对吧?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char** argv)
{
    int pipeIn[2];
    int pipeOut[2];

    if ((pipe(pipeIn)) == -1)
    {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    if ((pipe(pipeOut)) == -1)
    {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    pid_t child = fork();

    if (child == 0)
    {
        // This is child!

        if ((dup2(pipeIn[0], STDIN_FILENO)) == -1)
        {
            perror("dup2");
            exit(EXIT_FAILURE);
        }

        if ((dup2(pipeOut[1], STDOUT_FILENO)) == -1)
        {
            perror("dup2");
            exit(EXIT_FAILURE);
        }

        if ((dup2(pipeOut[1], STDERR_FILENO)) == -1)
        {
            perror("dup2");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeIn[0])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeOut[1])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        if ((execlp("sort", "-r", NULL)) == -1)
        {
            perror("execlp");
            exit(EXIT_FAILURE);
        }
    }
    else if (child == -1)
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }
    else
    {
        // This is parent!

        if ((close(pipeIn[0])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeOut[1])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        int dict = open("/usr/share/dict/words", O_RDONLY);

        if (dict == -1)
        {
            perror("open");
            exit(EXIT_FAILURE);
        }

        char buf[1024];
        int count;

        while ((count = read(dict, buf, sizeof(char) * 1024)) > 0)
        {
            putchar('.');

            if ((write(pipeIn[1], buf, count)) == -1)
            {
                perror("write 1");
                exit(EXIT_FAILURE);
            }
        }

        if (count == -1)
        {
            perror("read");
            exit(EXIT_FAILURE);
        }

        if ((close(dict)) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeIn[1])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        while ((count = read(pipeOut[0], buf, sizeof(char) * 1024)) > 0) // XXX
        {
            putchar('!');

            if ((write(STDOUT_FILENO, buf, count)) == -1)
            {
                perror("write 2");
                exit(EXIT_FAILURE);
            }
        }

        if (count == -1)
        {
            perror("read");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeOut[0])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }
    }

    return EXIT_SUCCESS;
}

感谢您的任何意见(请原谅双关语)。

Could anyone tell me what's wrong with this code?

In summary, it creates input and output pipes and fork-exec's the sort program. The parent reads the dictionary /usr/share/dict/words and writes it to the pipe that is dup2()'d to sort's standard in and, likewise, reads the output from it, printing it to the terminal (the standard output of the parent). Or, at least, that's what's supposed to be happening.

A backtrace says that the parent hangs at the read() on line 130 (marked with the comment 'XXX'). It's almost as though sort isn't aware of the end-of-file, but closing the write end of pipeIn should 'signal' this, right?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char** argv)
{
    int pipeIn[2];
    int pipeOut[2];

    if ((pipe(pipeIn)) == -1)
    {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    if ((pipe(pipeOut)) == -1)
    {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

    pid_t child = fork();

    if (child == 0)
    {
        // This is child!

        if ((dup2(pipeIn[0], STDIN_FILENO)) == -1)
        {
            perror("dup2");
            exit(EXIT_FAILURE);
        }

        if ((dup2(pipeOut[1], STDOUT_FILENO)) == -1)
        {
            perror("dup2");
            exit(EXIT_FAILURE);
        }

        if ((dup2(pipeOut[1], STDERR_FILENO)) == -1)
        {
            perror("dup2");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeIn[0])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeOut[1])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        if ((execlp("sort", "-r", NULL)) == -1)
        {
            perror("execlp");
            exit(EXIT_FAILURE);
        }
    }
    else if (child == -1)
    {
        perror("fork");
        exit(EXIT_FAILURE);
    }
    else
    {
        // This is parent!

        if ((close(pipeIn[0])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeOut[1])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        int dict = open("/usr/share/dict/words", O_RDONLY);

        if (dict == -1)
        {
            perror("open");
            exit(EXIT_FAILURE);
        }

        char buf[1024];
        int count;

        while ((count = read(dict, buf, sizeof(char) * 1024)) > 0)
        {
            putchar('.');

            if ((write(pipeIn[1], buf, count)) == -1)
            {
                perror("write 1");
                exit(EXIT_FAILURE);
            }
        }

        if (count == -1)
        {
            perror("read");
            exit(EXIT_FAILURE);
        }

        if ((close(dict)) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeIn[1])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }

        while ((count = read(pipeOut[0], buf, sizeof(char) * 1024)) > 0) // XXX
        {
            putchar('!');

            if ((write(STDOUT_FILENO, buf, count)) == -1)
            {
                perror("write 2");
                exit(EXIT_FAILURE);
            }
        }

        if (count == -1)
        {
            perror("read");
            exit(EXIT_FAILURE);
        }

        if ((close(pipeOut[0])) == -1)
        {
            perror("close");
            exit(EXIT_FAILURE);
        }
    }

    return EXIT_SUCCESS;
}

Thank you for any input (pardon the pun).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烟雨凡馨 2024-12-29 01:52:13

您的问题是您没有在智利过程中关闭管道未使用的末端。因此,您需要在 exec 之前的某个位置添加以下代码

    if ((close(pipeIn[1])) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }

    if ((close(pipeOut[0])) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }

Your problem is that you are not closing the unused ends of your pipe in the chile process. So you need to add the following code somewhere before the exec

    if ((close(pipeIn[1])) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }

    if ((close(pipeOut[0])) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文