C - mkfifo,ls - 不要停止

时间:2016-04-11 21:08:59

标签: c bash ls tr

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


int main(void) {


    if(mkfifo("fifo", S_IRWXU) < 0 && errno != EEXIST) {
        perror("Fifo error");
        exit(EXIT_FAILURE);
    }

    pid_t pid = fork();

    if(pid == 0) /*dziecko*/
    {
        int fifo_write_end = open("fifo", O_WRONLY);

        if(fifo_write_end < 0)
        {
            perror("fifo_write_end error");
            exit(EXIT_FAILURE);
        }

        if(dup2(fifo_write_end, STDOUT_FILENO) < 0)
        {
            perror("dup2 fifo_write_end error");
            exit(EXIT_FAILURE);
        }

        if(execlp("/bin/ls", "ls", "-al", NULL) < 0)
        {
            perror("execlp error");
            exit(EXIT_FAILURE);
        }

    }


    if(pid > 0) /*rodzic*/
    {
        int fifo_read_end = open("fifo", O_RDONLY);

        if(fifo_read_end < 0)
        {
            perror("fifo_read_end error");
            exit(EXIT_FAILURE);
        }
        if(dup2(fifo_read_end, STDOUT_FILENO) < 0)
        {
            perror("dup2 fifo_read_end error");
            exit(EXIT_FAILURE);
        }

        int atxt = open("a.txt", O_WRONLY|O_CREAT, S_IRWXU);

        if(atxt < 0)
        {
            perror("a.txt open error");
            exit(EXIT_FAILURE);
        }

        if(dup2(atxt,STDOUT_FILENO) < 0)
        {
            perror("dup2 atxt error");
            exit(EXIT_FAILURE);
        }

        if(execlp("/usr/bin/tr", "tr", "a-z", "A-Z", NULL) < 0)
        {
            perror("tr exec error");
            exit(EXIT_FAILURE);
        }

    }

    if(pid < 0)
    {
        perror("Fork error");
        exit(EXIT_FAILURE);
    }


    return 0;
}

程序不会停止。我不知道为什么 。它应该执行ls -al | tr a-z A-Z并将其写入文件a.txt。

如果有人可以,请解释我如何做ls-al | tr a-z A-Z | tr A-Z a-z&gt; a.txt。对于另一个我需要第二个mkfifo对吗?我不确定它是如何工作的,如果我应该在这里关闭写或读取描述符。 “管道”是nesesery。

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

在管道关闭之前,管道的读取端不会报告EOF。在所有引用它的描述符关闭之前,管道不会关闭。在调用dup2之后,管道将被原始FD和您欺骗它的描述符引用。您需要关闭原始FD。

    if(dup2(fifo_write_end, STDOUT_FILENO) < 0)
    {
        perror("dup2 fifo_write_end error");
        exit(EXIT_FAILURE);
    }
    close(fifo_write_end);
    if(execlp("/bin/ls", "ls", "-al", NULL) < 0)
    {
        perror("execlp error");
        exit(EXIT_FAILURE);
    }

另一个问题是,运行tr的流程需要将FIFO复制到stdin,而不是stdout。所以

    if(dup2(fifo_read_end, STDOUT_FILENO) < 0)
    {
        perror("dup2 fifo_read_end error");
        exit(EXIT_FAILURE);
    }

应该是

    if(dup2(fifo_read_end, STDIN_FILENO) < 0)
    {
        perror("dup2 fifo_read_end error");
        exit(EXIT_FAILURE);
    }