Fork-exec管道重定向问题

时间:2011-12-19 00:10:10

标签: c linux exec fork pipe

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

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

回溯表示父母在第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;
}

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

1 个答案:

答案 0 :(得分:2)

您的问题是您没有在智利过程中关闭管道的未使用端。因此,您需要在exec

之前的某处添加以下代码
    if ((close(pipeIn[1])) == -1)
    {
        perror("close");
        exit(EXIT_FAILURE);
    }

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