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);
}
There are few problems with your program:
- You are not checking returned values of read, write and execle in prog2.c
- 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 ).
- Also "off" you are sending is 3 characters long but without including null termination.
- 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!
- 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.
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;
}