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

C 子进程和父进程之间的通信,c,pipe,fork,C,Pipe,Fork,我试图在两个进程之间进行通信,一个是发送指令的父进程,另一个是返回响应的子进程 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

我试图在两个进程之间进行通信,一个是发送指令的父进程,另一个是返回响应的子进程

    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);

}
在子进程中:子消息接收来自父进程的消息

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);
    }

}

尝试减少代码,子代码中存在错误的关闭:

       close(send[1]);
       dup2(send[0], 0);
       close(send[0]);
在dup2之后,filedescriptor发送[0]与发送管道输入不再相关,它可能意外地关闭子进程中的其他filedescriptor

您的代码无法从父级的stdout与子级的stdin进行通信。 下面是一个小示例,它将父对象的stdout重定向到管道的输入,将管道的输出重定向到子对象的stdin

#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);
            }
        }
    }
}
#包括
#包括
int main(int argc,字符**argv){
int-send[2];
如果(管道(发送)!=0){
佩罗(“管道”);
}否则{
int-pid=fork();
if(pid<0){
佩罗尔(“福克”);
}
否则,如果(pid>0){
//父进程
关闭(发送[0]);//关闭管道输入
dup2(发送[1],1);//用管道输出替换标准输出
//向孩子发送消息
fprintf(stdout,“发送到子对象\n”);
fflush(stdout);
}否则{
//子进程
关闭(发送[1]);//关闭管道输出
dup2(发送[0],0);//用管道输入替换标准输入
字符消息[2048];
如果(fgets(消息,2048,标准输入)!=NULL){
fprintf(stderr,“来自父级的消息:%s”,消息);
}
}
}
}

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

       close(send[1]);
       dup2(send[0], 0);
       close(send[0]);
在dup2之后,filedescriptor发送[0]与发送管道输入不再相关,它可能意外地关闭子进程中的其他filedescriptor

您的代码无法从父级的stdout与子级的stdin进行通信。 下面是一个小示例,它将父对象的stdout重定向到管道的输入,将管道的输出重定向到子对象的stdin

#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);
            }
        }
    }
}
#包括
#包括
int main(int argc,字符**argv){
int-send[2];
如果(管道(发送)!=0){
佩罗(“管道”);
}否则{
int-pid=fork();
if(pid<0){
佩罗尔(“福克”);
}
否则,如果(pid>0){
//父进程
关闭(发送[0]);//关闭管道输入
dup2(发送[1],1);//用管道输出替换标准输出
//向孩子发送消息
fprintf(stdout,“发送到子对象\n”);
fflush(stdout);
}否则{
//子进程
关闭(发送[1]);//关闭管道输出
dup2(发送[0],0);//用管道输入替换标准输入
字符消息[2048];
如果(fgets(消息,2048,标准输入)!=NULL){
fprintf(stderr,“来自父级的消息:%s”,消息);
}
}
}
}

发送消息的代码在哪里?和接收信息?顺便说一句,您应该刷新管道(也可能是换行符),以确保发送字符串。哪些消息?你要把它们送到哪里去?父进程的
stdout
在哪里?为什么?添加在我如何处理从父进程到子进程的消息中。感谢您的反馈。如果这是在Linux上,
strace
是一个很好的调试工具(或者在本例中是
strace-f
)。当系统函数,如
fork()
pipe()
失败时,应该将错误消息和系统认为错误发生的原因一起输出到
stderr
。最简单的方法是调用
peror()
发送消息的代码在哪里?和接收信息?顺便说一句,您应该刷新管道(也可能是换行符),以确保发送字符串。哪些消息?你要把它们送到哪里去?父进程的
stdout
在哪里?为什么?添加在我如何处理从父进程到子进程的消息中。感谢您的反馈。如果这是在Linux上,
strace
是一个很好的调试工具(或者在本例中是
strace-f
)。当系统函数,如
fork()
pipe()
失败时,应该将错误消息和系统认为错误发生的原因一起输出到
stderr
。最简单的方法是调用
peror()