Завершение STDIN_FILENO, чтобы сообщить хвосту, что ввод сделан - PullRequest
0 голосов
/ 29 марта 2020

Итак, я работал над заданием, копируя то, что ls -1 | голова -3 | Хвост -1 будет использовать каналы в c, и я придумал это.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#define die(e) do { fprintf(stderr, "%s\n", e); exit(EXIT_FAILURE); } while (0);

void ForkAndLSAndPipeOutput(int *linkout){
    pid_t pid;
    int status;

    pid = fork();
    if(pid < 0){
        die("forkandls");
    }

    if(pid == 0){

        //make the output pipes to linkout
        close(linkout[0]);
        dup2(linkout[1],STDOUT_FILENO);
        close(linkout[1]);

        char * argv[] = {"ls","-1", NULL};
        execv("/usr/bin/ls",argv);
    }else{
        wait(&status);
        return;
    }
}

void ForkAndHeadAndPipeOutput(int * linkin, int * linkout){
    pid_t pid;
    int status;
    char endout[2] = "\0";

    pid = fork();
    if(pid < 0){
        die("forkandhead");
    }

    if(pid == 0){

        //make the input to linkin
        close(linkin[1]);
        dup2(linkin[0],STDIN_FILENO);
        close(linkin[0]);

        //make the output pipes to linkout
        close(linkout[0]);
        dup2(linkout[1],STDOUT_FILENO);
        close(linkout[1]);

        char * argv[] = {"head","-3", NULL};
        execv("/usr/bin/head",argv);
    }else{
        wait(&status);
        return;
    }
}

void printPipeRead(int * pipe){
    char buf[4096];
    read(pipe[0],buf,4096);
    printf("%s",buf);
}

void ForkAndTailAndPipeOutput(int * linkin, int * linkout){
    pid_t pid;
    int status;

    pid = fork();
    if(pid  < 0){
        die("forkandhead");
    }
    if(pid == 0){

        //make the input to linkin
        close(linkin[1]);
        dup2(linkin[0],STDIN_FILENO);
        close(linkin[0]);

        //make the output pipes to linkout
        close(linkout[0]);
        dup2(linkout[1],STDOUT_FILENO);
        close(linkout[1]);


        char * argv[] = {"tail","-1", NULL};
        execv("/usr/bin/tail",argv);
    }else{
        wait(&status);
        return;
    }
}


int main() {
    int link1[2];
    int link2[2];
    int link3[2];
    pid_t pid;
    char out[4096];

    if (pipe(link1)<0)
        die("pipe1");
    if (pipe(link2)<0)
        die("pipe2");
    if (pipe(link3)<0)
        die("pipe3");

    ForkAndLSAndPipeOutput(link1);
    ForkAndHeadAndPipeOutput(link1,link2);
    ForkAndTailAndPipeOutput(link2,link3);
    read(link3[0],out,4096);
    printf("%s\n",out);
    return 0;
}

В результате произошел сбой, программа продолжала что-то ждать. После некоторых исследований я предположил, что это из-за того, что tail не распознает входные данные как закрытые. Это правильно? если да, то как мне заставить хвост признать это?

На другой ноте учитель дал мне ответ, и это было что-то вроде этого, и это сработало, почему?

void ForkAndHeadAndPipeOutput(int * linkin, int * linkout){
    pid_t pid;
    int status;
    char endout[2] = "\0";

    pid = fork();
    if(pid < 0){
        die("forkandhead");
    }

    if(pid == 0){

        //make the input to linkin
        close(linkin[1]);
        dup2(linkin[0],STDIN_FILENO);
        close(linkin[0]);

        //make the output pipes to linkout
        close(linkout[0]);
        dup2(linkout[1],STDOUT_FILENO);
        close(linkout[1]);

        char * argv[] = {"head","-3", NULL};
        execv("/usr/bin/head",argv);
    }else{
        wait(&status);
        close(linkout[1]);
        dup2(linkout[0], STDIN_FILENO);
        char * argv[] = {"tail","-1", NULL};
        execv("/usr/bin/tail",argv);
        return;
    }
}

Это в основном только выполнял форк-исполнение как родительский руководитель. Учитель не может дать никакого объяснения, а также почему это работает, любое объяснение?

...