带有dup2()-ed描述符的FILE *流— stdin不起作用

时间:2019-01-11 19:29:57

标签: c linux pipe

派生一个孩子并dub2()-将其stdin描述符传递到管道的读取端(其写入端在父进程中)后,使用read(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()复制到下行链路[0](=从写入父级开始的管道的读取端))和printf()以stdout接收到的竞争 如果使用read()(基于描述符)进行读取,则一切正常。使用fgets()或scanf()(基于流)读取时,不会打印任何数据。

我在这里想念什么?

1 个答案:

答案 0 :(得分:1)

fgets()读取一行,但是您的父进程从不发送一行文本。因此,您需要在string

中添加换行符
 char string[]="MY TEST STRING\n";

read()仅在可用时读取管道中的所有内容-它不会尝试读取所有可能的数据,直到换行符为止,这就是为什么使用{{1 }}

即使您不发送换行符,当管道的写入端关闭时,read()也会返回。但是,您在父流程中创建的管道将被复制到子流程中。

这意味着,当父进程退出时,其管道的写端将关闭-但在子进程中不会关闭管道的写端-导致在父进程退出时管道仍处于打开状态。

因此,请确保在子进程中关闭管道的写入端,因为您不需要它:

fgets()