【问题标题】:Communication between parent and child though stdout and stdin通过 stdout 和 stdin 进行父子之间的通信
【发布时间】:2017-02-01 10:04:19
【问题描述】:

我对 C 中的管道和分叉比较陌生,

我有一个父进程和一个子进程,并尝试在它们之间进行通信。

我创建了一个管道,这样:父级的标准输出将连接到子级的标准输入,子级的标准输出将连接到父级的标准输入。

我通过尝试让父级通过其标准输出发送“A”来测试这一点,然后子级将从其标准输入接收“A”,之后它应该将“B”从其标准输出发送回父级的标准输入。

这是我的代码,

bool pget_input(void){
    char buffer[80];
    fprintf(stdout,"A");
    fprintf(stderr,"Parent sent out 'A' to child \n");
    do{
        if (!fgets(buffer, 20, stdin)) {
            fprintf(stderr,"Parent failed to recieve from child\n");
            return false;                                        
        }
        fprintf(stderr,"Parent receiving from child\n");
        if(strcmp(buffer, "B")==0){
            fprintf(stderr,"Parent success recieve child's reply");
        }
        continue;
    }while(true);
}
int main(int argc, char** argv){

    pid_t pid = fork();
    int pipe1[2];
    int pipe2[2];

    if (pipe(pipe1)==-1 || pipe(pipe2)==-1){
        fprintf(stderr,"pipe failed\n");
        exit(1);
    }

    if(pid > 0){
        //parent
        close(STDIN_FILENO);    //close stdin
        dup(pipe1[0]);          //replace stdin with pipe1 read
        close(STDOUT_FILENO);   //close stdout
        dup(pipe2[1]);          //replace stdout with pipe2 write
        //close pipe1 and pipe2 read write
        close(pipe1[0]);        
        close(pipe1[1]);
        close(pipe2[0]);
        close(pipe2[1]);
        pget_input();
        wait(0);
    }else if(pid ==0){
        //child
        close(STDOUT_FILENO);   //close stdout
        dup(pipe1[1]);          //replace stdout with pipe1 write
        close(STDIN_FILENO);    //close stdin
        dup(pipe2[0]);          //replace stdin with pipe2 read

        //close pipe1 and pipe2 read write
        close(pipe1[0]);        
        close(pipe1[1]);
        close(pipe2[0]);
        close(pipe2[1]);

        execl("./child", "not matter", NULL);
        perror("execvp failed");
           exit(1);

    }else{
        fprintf(stderr,"fork failed\n");
        exit(1);
    }
    fprintf(stderr,"Exiting\n");
    exit(1);

}

./child:

bool cget_input(void){
    char buffer[80], command[80];
    fprintf(stderr,"Child trying receive from parent\n");
    do{
        if (!fgets(buffer, 20, stdin)) {
            fprintf(stderr,"child failed to receive from parent\n");
            return false;                                        
        }
        sscanf(buffer, "%s", command);
        if(strcmp(buffer, "A") == 0){
            fprintf(stderr,"Child received 'A' from Parent and sending out 'B'\n");
            fprintf(stdout, "B");
        }
        continue;
    }while(true);
}
int main ()
{

    if(!cget_input()){
        return 0;
    }

    return 1;
}

结果,父母和孩子的标准输入都没有收到任何东西, 没有通过

if (!fgets(buffer, 20, stdin)) 

谁能指出我的代码出了什么问题? 谢谢,

【问题讨论】:

  • 我不明白你如何用管道替换标准输入/输出。我也看不到它的区域,因为您无论如何都在使用fprintf 和fgets,它们不默认为stdio。为什么不将它传递给你的管道而不是使用 stdio?
  • 这是我的任务的一部分。
  • 基本上任务是创建一个可以通过stdin和stdout与HUB通信的游戏

标签: c linux pipe fork exec


【解决方案1】:

您必须在分叉之前设置管道。

这里是需要完成的顺序的大纲:

  1. 使用 pipe() 创建管道
  2. 分叉
  3. 父母和孩子各自关闭管道的正确端。
  4. 如果需要,父母和孩子可以使用 dup() 和 close() 重定向标准输出、标准输入
  5. 此时,您可以在子进程中 exec() 一个新程序,该程序不需要知道已经发生的重定向。

分叉后,父子进程是两个不同的进程,此时父进程无权修改子进程的文件描述符。任何共享文件描述符都必须在 fork 之前设置。

【讨论】:

    猜你喜欢
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-20
    相关资源
    最近更新 更多