Two way pipe communication between parent and chil

2019-08-15 08:22发布

问题:

I'm trying to create two-way communication between parent and child processes using 2 pipes in C.the prog1 running in child1 I want to read 3+4+5 from prog1 after that send something to prog1 with write but I could not. Where is the wrong?

/* prog1.c */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void
main(void){
    int FD;
unsigned int buf;
char buf[15];

printf("7+5+11=?\n");
FD=read(0,buf,10);
if(FD<0){
    perror("FAIL\n");
exit(EXIT_FAILURE);
}
     printf("TAKED:%s\n",buf);
}

prog2.c

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
void ERR_SYS(const char *msg);
int
main(void){
    char buf[15];
    int pipe1[2];
    int pipe2[2];
    pid_t childpid;

    memset(buf,'\0',14);

    if(pipe(pipe1) < 0 || pipe(pipe2) < 0)
     ERR_SYS("fail_pipe");

    if((childpid = fork()) < 0)
     ERR_SYS("fail_fork");

    if(childpid==0)
    {
      dup2(pipe2[1],1);
          dup2(pipe1[0],0);
      close(pipe1[1]);
          close(pipe2[0]);
      close(pipe2[1]);
      close(pipe1[0]);
          //close(1);
          //close(0);
      execle("./prog1",NULL,NULL,NULL);
    }else{

     close(pipe1[0]);
     close(pipe2[1]);
     read(pipe2[0],buf,4); /*I hope to read 3+4+5*/
     printf("BuF::%s\n",buf);
     write(pipe1[1],"off",3);/*send {off}*/
     wait(NULL);
    }
 return 0;
 }

 void 
 ERR_SYS(const char *msg)
 {
     perror(msg);
     exit(EXIT_FAILURE);
 }

回答1:

There are few problems with your program:

  1. You are not checking returned values of read, write and execle in prog2.c
  2. You are sending "7+5+11=?\n" string which is 10 characters long but only expecting 4 characters ( 3+4+5 is not even four characters ).
  3. Also "off" you are sending is 3 characters long but without including null termination.
  4. When you read from an fd you will in both cases not get null terminated string and then you are trying to printf it. It's a quick way to undefined behaviour. Put an '\0' after the end of buffer you read from any file descriptor!
  5. Especially what read returns is very important as it tells you how many characters were read. You should never ignore returned value of read (in some cases it's the same with write function).

Next time also provide some output of your program as it will be easier to give some help.



回答2:

I didn't follow all your logic in setting up the pipes, so I modified and hopefully clarified your original. I should note that for whatever reason I named fd_in and fd_out from the external program's (prog1) point of view (e.g. fd_out is where prog1 is writing to, fd_in is where prog1 is reading from).

Here's the contents of my prog3.c:

...
#define READ_END 0
#define WRITE_END 1
void ERR_SYS(const char *msg);
int main(void) {

    char buff[15];
    char *msg = "hello";
    int fd_out[2];
    int fd_in[2];
    int nbytes;
    pid_t childpid;

    if(pipe(fd_out) < 0 || pipe(fd_in) < 0) {
            ERR_SYS("fail_pipe");
    }

    if((childpid = fork()) < 0) { 
            ERR_SYS("fail_fork");
    }

    if(childpid==0) { //child 
            //connect the write end of fd_out to stdout
            dup2(fd_out[WRITE_END], STDOUT_FILENO);
            close(fd_out[WRITE_END]);
            //connect the read end of fd_in to stdin
            dup2(fd_in[READ_END], STDIN_FILENO);
            close(fd_in[READ_END]);
            //the exec'd prog1 will inherit the streams
            execlp("./prog1", "prog1", NULL); //TODO: check return
    } else { //parent
            nbytes = write(fd_in[WRITE_END], msg, strlen(msg));
            //TODO: handle any errors from write
            nbytes = read(fd_out[READ_END],buff,sizeof(buff)-1);
            //TODO: handle any errors from read
            buff[nbytes] = '\0';
            printf("contents of buff::%s",buff);
    }
    return 0;
}
void ERR_SYS(const char *msg) {
    perror(msg);
    exit(EXIT_FAILURE);
}

And here's the contents of my prog1.c

int main(void){
    char buff[15];
    int nbytes;
    nbytes = read(STDIN_FILENO, buff, sizeof(buff)-1);
    buff[nbytes] = '\0';
    printf("%s world\n", buff);
    return 0;

}