Reputation: 869
I am trying to write a simple program in C where some content is passed through a pipe to a child process twice, each time with a different value:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#define READ 0
#define WRITE 1
int main(){
int myPipe[2];
if (pipe(myPipe) < 0) {
fprintf(stderr,"Pipe Error!");
return -1;
}
pid_t pid = fork();
if (pid < 0)
perror("Error forking!");
else if(pid > 0){
// Master
char var[4];
// Sends the first value.
sprintf(var, "foo");
close(myPipe[READ]);
write(myPipe[WRITE], var, sizeof(var));
close(myPipe[WRITE]);
// Sends the second value.
sprintf(var, "bar");
close(myPipe[READ]);
write(myPipe[WRITE], var, sizeof(var));
close(myPipe[WRITE]);
wait(NULL);
return 0;
}
else if (pid == 0){ // Child
char received[4];
// Reads the first value.
close(myPipe[WRITE]);
read(myPipe[READ], received, sizeof(received));
close(myPipe[READ]);
printf("I have received the following value: %s\n", received);
// Reads the second value.
close(myPipe[WRITE]);
read(myPipe[READ], received, sizeof(received));
close(myPipe[READ]);
printf("I have received the following value: %s\n", received);
return 0;
}
}
Seems, though, the output is not the expected, as variable received
never changes its value:
I have received the following value: foo
I have received the following value: foo
...when the desired output is:
I have received the following value: foo
I have received the following value: bar
I can't understand why this happens, as I think - probably wrongly - pipes get overwritten every time they are used the same way you can perform:
int i = 0;
printf("%i\n", i);
i = 4;
printf("%i", i);
...which would return:
0
4
Why isn't this phenomenon happening in pipes?
Upvotes: 1
Views: 594
Reputation: 24738
Why isn't this phenomenon happening in pipes?
You are calling close()
more than you should.
The parent process is closing the writing end of the pipe before the second write (i.e: "bar"). The child process is closing the reading end of the pipe before the second read. Therefore, your second read in the child process is actually not reading anything from the pipe, since the file descriptor passed to read()
is not valid. Note that, the second write()
in the parent process didn't succeed either for the same reason.
Besides, pipe ends that have been already closed are being closed again: the reading end in the parent and the writing end in the child.
By just removing those inconvenient calls to close()
, the code produces exactly what you are expecting :
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#define READ 0
#define WRITE 1
int main(){
int myPipe[2];
if (pipe(myPipe) < 0) {
fprintf(stderr,"Pipe Error!");
return -1;
}
pid_t pid = fork();
if (pid < 0)
perror("Error forking!");
else if(pid > 0){
// Master
char var[4];
// Sends the first value.
sprintf(var, "foo");
close(myPipe[READ]);
write(myPipe[WRITE], var, sizeof(var));
// Sends the second value.
sprintf(var, "bar");
write(myPipe[WRITE], var, sizeof(var));
close(myPipe[WRITE]);
wait(NULL);
return 0;
}
else if (pid == 0){ // Child
char received[4];
// Reads the first value.
close(myPipe[WRITE]);
read(myPipe[READ], received, sizeof(received));
printf("I have received the following value: %s\n", received);
// Reads the second value.
read(myPipe[READ], received, sizeof(received));
printf("I have received the following value: %s\n", received);
return 0;
}
return 0;
}
That is, the output is:
I have received the following value: foo
I have received the following value: bar
Upvotes: 3