FILE * потоки с dup2 () - ed дескрипторы - stdin не работает - PullRequest
0 голосов
/ 11 января 2019

После разветвления потомка и dub2 () - передача его дескриптора stdin в конец чтения канала (его конец записи находится в родительском процессе), чтение с чтением (0, ...) (на основе дескриптора) работает хорошо. Но чтение с помощью fgets (stdin, ...) (основанное на потоке) не работает. Почему?

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int main(){
    char string[]="MY TEST STRING";
    pid_t pid;
    int bufSize=80;
    char rBuf[bufSize];
    int downlink[2], wrlen=0, rdlen=0, status;
    memset(rBuf,0,bufSize);

    if (pipe (downlink) == -1){
        printf("Error with pipe()\n");
        exit(4);
    }

    pid=fork();
    if (pid>0){              //parent

        wrlen=wrlen+write(downlink[1], string, strlen(string)+1);
        //dprintf(downlink[1],"%s", string);
        sleep(6);

    }
    else if (pid == 0){      // child

        dup2(downlink[0],STDIN_FILENO);

        //rdlen=read(downlink[0], rBuf, bufSize);          //works
        //rdlen=read(STDIN_FILENO, rBuf, bufSize);           //works        
        //scanf("%s", rBuf);fflush(stdin);                 //doesn't work, reads up to first blank
        //scanf(stdin,"%s", rBuf);fflush(stdin);           //doesn't work, reads up to first blank
        fgets(rBuf, bufSize, stdin);fflush(stdin);       //doesn't work
        printf("c: %s", rBuf), fflush(stdout);
        //status =execl("/usr/bin/octave","octave","--no-gui",NULL);
        //status =execl("/usr/bin/man","man",NULL);

        //printf("c: status%d", status), fflush(stdout);

    }
    else{                    //error
        printf("Error with fork()\n");
        exit(4);
    }
return 0;
}

В этом коде дочерний элемент fork () должен читать из stdin (который dub2 () ed в downlink [0] (= конец чтения канала из записи родителя)) и printf () для вывода полученного contets. Если чтение происходит с помощью read () (на основе дескриптора), все работает нормально. При чтении с помощью fgets () или scanf () (на основе потока) данные не печатаются.

Что мне здесь не хватает?

1 Ответ

0 голосов
/ 11 января 2019

fgets() читает строку, но ваш родительский процесс никогда не отправляет строку текста. Поэтому вам нужно добавить новую строку в string

 char string[]="MY TEST STRING\n";

read() однако просто читает все, что находится в канале, когда он становится доступным - он не пытается прочитать все данные, которые он может, до символа новой строки, поэтому вы возвращаете данные при использовании read()

Даже если вы не отправляете новую строку, fgets() вернется, когда конец записи канала будет закрыт. Однако канал, который вы создаете в родительском процессе, копируется в дочерний процесс.

Это означает, что при выходе из родительского процесса его конец записи канала закрыт, но не конец записи канала в дочернем процессе, что приводит к тому, что канал все еще остается открытым при выходе из родительского процесса.

Поэтому убедитесь, что вы закрыли () конец записи канала в вашем дочернем процессе, так как он вам не нужен:

else if (pid == 0){      // child
        close(downlink[1]);
        dup2(downlink[0],STDIN_FILENO);
...