使用两个管道的双向进程间通信 [英] Bi-directional inter-process communication using two pipes

查看:123
本文介绍了使用两个管道的双向进程间通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写分叉子流程并使用管道与其通信的代码.我正在使用两个管道-一个用于写入,另一个用于从子流程的标准流中读取.这是我到目前为止的内容:

I am trying to write code that forks a subprocess and communicates with it using pipes. I am using two pipes - one for writing to, and the other for reading from the standard streams of the subprocess. Here's what I have so far:

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

void read_move(int fd)
{
    FILE *stream = fdopen(fd, "r");
    char c;
    setvbuf(stream, NULL, _IONBF, BUFSIZ);  
    while ((c = fgetc(stream)) != EOF)
    {
        putchar(c);
    }
    fclose(stream);
}

void write_move(int fd, const char *move)
{
    FILE *stream = fdopen(fd, "w");
    setvbuf(stream, NULL, _IONBF, BUFSIZ);
    fprintf(stream, "%s", move);
    fclose(stream);
}

int main() {
    pid_t pid;
    int wpipe[2];
    int rpipe[2];
    if (pipe(wpipe) || pipe(rpipe))
    {
        fprintf(stderr, "Pipe creation failed.\n");
        return EXIT_FAILURE;
    }
    pid = fork();
    if (pid == 0)
    {
        /* gnuchess process */
        setvbuf(stdin, NULL, _IONBF, BUFSIZ);
        setvbuf(stdout, NULL, _IONBF, BUFSIZ);
        setvbuf(stderr, NULL, _IONBF, BUFSIZ);
        dup2(wpipe[0], STDIN_FILENO);
        dup2(rpipe[1], STDOUT_FILENO);
        dup2(rpipe[1], STDERR_FILENO);
        close(wpipe[0]);
        close(wpipe[1]);
        close(rpipe[0]);
        close(rpipe[1]);
        if (execl("/usr/games/gnuchess", "gnuchess", "-x", NULL) == -1)
        {
            fprintf(stderr, "Exec failed.\n");
            return EXIT_FAILURE;
        }
        return EXIT_SUCCESS;
    }

    /* parent process */

    printf("Sending move to GNU Chess... \n");
    close(wpipe[0]); /* Close other end */
    write_move(wpipe[1], "c3\n");   

    printf("Reading response... \n");
    close(rpipe[1]); /* Close other end */
    read_move(rpipe[0]);

    /* clean up */  
    close(wpipe[1]);
    close(rpipe[0]);    

    /* kill gnuchess */
    kill(pid, SIGTERM);

    return EXIT_SUCCESS;
}

上面程序的输出是

Sending move to GNU Chess... 
Reading response... 

它被卡在read_move函数中的getline调用上,等待输入.但是我不知道怎么可能,因为我已经关闭了另一端.

It gets stuck at the getline call in the read_move function, waiting for input. But I don't understand how that's possible, since I have closed the other end.

我在做什么错了?

我更改了read_move方法,并在dup2调用之后关闭了子进程中的管道末端.

I changed the read_move method and closed the pipe ends in the child process after the dup2 calls.

推荐答案

您没有在子进程中关闭wpipe.因此,实际上,您在启动时实际上是将7个文件描述符传递给gnu国际象棋-dup'ed stdin,stdout和stderr;在wpipe中有2个描述符,在rpipe中有2个描述符.

You're not closing wpipe in the child process. So you're actually passing 7 file descriptors to gnu chess when you start it - the dup'ed stdin, stdout and stderr; the 2 descriptors in wpipe, and the 2 descriptors in rpipe.

如果您使用的是Linux,请在程序运行时找出gnu围棋的进程ID,然后执行ls/proc//fd查看其所有文件描述符.

If you're on linux, find out the process id of gnu chess while your program is running, and do a ls /proc//fd to see all its file descriptors.

添加后

close(wpipe [0]); 关闭(wpipe [1]); 关闭(rpipe [0]); close(rpipe [1]);

close(wpipe[0]); close(wpipe[1]); close(rpipe[0]); close(rpipe[1]);

在dup2()和execl()之间,您应该没事.

between the dup2()s and the execl(), you should be ok.

(这仍然省略了错误处理,例如dup2()之一失败的情况,或者更糟的是,您的程序在调用pipe()之前已关闭fds [0,1,2]之一,因此的标准描述符不小心被换成了管道.但是我想这不是重点.)

(This still omits error handling, like the case that one of the dup2()s fails, or, even worse, your program has closed one of the fds [0, 1, 2] before calling pipe() so one of the standard descriptors gets replaced with a pipe accidentially. But i guess that's not the point here.)

这篇关于使用两个管道的双向进程间通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆