【问题标题】:C - mkfifo , ls - don't stopC - mkfifo , ls - 不要停止
【发布时间】:2016-04-11 21:08:58
【问题描述】:
#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 > a.txt 。对于另一个 tr,我需要第二个 mkfifo 对吗?我不确定它是如何工作的,我是否应该在此处关闭写入或读取描述符。使用“管道”时,它是 nesesery。

感谢您的帮助!

【问题讨论】:

    标签: c bash ls tr


    【解决方案1】:

    在管道关闭之前,管道的读取端不会报告 EOF。直到 all 引用它的描述符都关闭后,管道才会关闭。在你调用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);
        }
    

    【讨论】:

    • 谢谢,仔细阅读后它可以工作,但是第二个 TR 怎么办。我需要第二个 mkfifo?
    • 是的,每个管道都需要一个 FIFO。顺便说一句,你为什么使用 FIFO 而不是调用pipe()
    • 这是我学习中的一项任务。要清楚,第二个fifo应该在哪里?会有2个叉子,第一个喜欢起来,第二个孩子做“孙子”对吧?
    • 所以应该有,孙子中的 ls,孩子中的第一个 tr,父母中的第二个 tr,但是我应该在孩子之后但在父母之前制作第二个 mkfifo 吗?
    • 在哪里创建第二个 FIFO 并不重要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多