子进程和父进程之间的通信

Posted

技术标签:

【中文标题】子进程和父进程之间的通信【英文标题】:Communicating between a child process and a parent process 【发布时间】:2018-03-04 09:23:32 【问题描述】:

我正在尝试在两个进程之间进行通信,一个发送指令的父进程和一个返回响应的子进程。

    void create_player(Game *g, Player *p, int player, char* command) 

       int send[2];
       int receive[2];
       int file;

        if(pipe(send)!=0) 
            _exit(99);
        
        if(pipe(receive)!=0) 
            _exit(99);
        

        g->player[player].id = fork();

        if(g->player[player].id < 0) 
            fprintf(stderr, "Unable to start subprocess\n");
            fflush(stderr);
            exit(5);
        

        //Parent process
        else if(g->player[player].id>0) 
            g->player[player].send = fdopen(send[1], "w");
            g->player[player].receive = fdopen(receive[0], "r");

            close(send[0]);
            close(receive[1]);

        //Child process
          else 

           close(send[1]);
           close(receive[0]);
           dup2(send[0], 0);
           dup2(receive[1], 1);
           close(send[0]);
           close(receive[1]);

           file = open("/dev/null", O_WRONLY);

           for(i =0; i < player; i++) 
                fclose(g->player[i].send);
                fclose(g->player[i].receive);
            

            char width[1024];
            char playerId[26];
            char numOfPlayers[26];
            char seed[1024];
            char numOfCarriages[1024];

            sprintf(seed, "%d", g->seed);
            sprintf(width, "%d", g->numOfCarriages);
            sprintf(playerId, "%d", player);
            sprintf(numOfPlayers, "%d", g->numOfPlayers);

            char* args[] = command, numOfPlayers, playerId, width, seed, NULL;

            execlp(command, command, numOfPlayers, playerId, width, seed, (char*) 0);

            _exit(99);


当我运行代码块来创建子进程时,没有任何消息通过(父标准输出 -> 子标准输入)发送。我添加了一些示例来展示我如何处理消息传递。任何帮助将不胜感激。

在父进程中:父进程向子进程发送消息

//Send message to start the game
void send_startGame(Game *g) 
    fprintf(g->player[g->currentPlayer].send, "startGame\n");
    fflush(g->player[g->currentPlayer].send);

在子进程中:子消息从父进程接收消息

void read_message(Game *g) 
    char message[2048];

    if(fgets(message, 2048, stdin) == NULL) 
        fprintf(stderr, "Error in message\n");
    

    //Receive start game message
    if(strncmp("startGame\n", message, 9)==0)
        start_game(g);
    


【问题讨论】:

发送消息的代码在哪里?并接收消息?顺便说一句,您应该刷新管道(也可能是换行符),以确保发送字符串。 哪些消息?你要把它们送到哪里?所涉及的父母的stdout 在哪里?为什么? 添加了我如何处理从父进程到子进程的消息。感谢您的反馈。 如果这是在 Linux 上,strace 是一个很好的调试工具(或者在这种情况下是 strace -f)。 当系统函数,如fork()pipe()失败时,应该输出到stderr,连同你的错误信息,系统认为错误发生的原因。最简单的方法是致电perror() 【参考方案1】:

尽量减少你的代码,子代码中有错误的关闭:

       close(send[1]);
       dup2(send[0], 0);
       close(send[0]);

在 dup2 之后,文件描述符 send[0] 与发送管道输入不再相关,它可能会意外关闭子进程中的另一个文件描述符。

您的代码不会从父级的标准输出到子级的标准输入进行通信。 以下是一个小示例,将父级的标准输出重定向到管道的输入,将管道的输出重定向到子级的标准输入。

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

int main(int argc, char **argv) 
    int send[2];
    if(pipe(send)!=0) 
        perror("pipe");
     else 
        int pid = fork();
        if(pid < 0) 
            perror("fork");
        
        else if(pid>0) 
            //Parent process
            close(send[0]);  // close pipe input 
            dup2(send[1], 1); // replace stdout with pipe output

            // send message to child
            fprintf(stdout, "send to child\n");
            fflush(stdout);
          else 
            //Child process                     
            close(send[1]);      // close pipe output                       
            dup2(send[0], 0); // replace stdin with pipe input

            char message[2048];
            if(fgets(message, 2048, stdin) != NULL) 
                fprintf(stderr, "message from parent:%s", message);
            
        
    

Ideone link

【讨论】:

以上是关于子进程和父进程之间的通信的主要内容,如果未能解决你的问题,请参考以下文章

什么是子进程和父进程

(疑问)进程控制---vfork 函数

fork出的子进程和父进程

fork出的子进程和父进程

当子进程和父进程在 Perl 中写入同一个日志文件时进程卡住(在 Windows 中)

C 语言编程 — 进程操作