簡體   English   中英

使用兩個管道的雙向進程間通信

[英]Bi-directional inter-process communication using two pipes

我正在嘗試編寫分叉子流程並使用管道與之通信的代碼。 我正在使用兩個管道-一個用於寫入,另一個用於從子流程的標准流中讀取。 這是我到目前為止的內容:

#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調用上,等待輸入。 但是我不知道怎么可能,因為我已經關閉了另一端。

我究竟做錯了什么?

編輯:我更改了read_move方法並在dup2調用后關閉了子進程中的管道末端。

您不會在子進程中關閉wpipe。 因此,實際上,您在啟動時實際上將7個文件描述符傳遞給gnu國際象棋-dup'ed stdin,stdout和stderr; wpipe中的2個描述符,rpipe中的2個描述符。

如果您使用的是Linux,請在程序運行時找出gnu Chess的進程ID,然后執行ls / proc // fd查看其所有文件描述符。

一旦添加

關閉(wpipe [0]); 關閉(wpipe [1]); 關閉(RPIPE [0]); 關閉(RPIPE [1]);

在dup2()和execl()之間,您應該沒問題。

(這仍然忽略了錯誤處理,例如dup2()之一失敗的情況,或者甚至更糟的是,您的程序在調用pipe()之前已關閉fds [0,1,2]之一,因此是標准之一描述符被意外地替換為管道。但是我想這不是重點。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM