I'm creating a child process using fork() and in the parent process I'm taking the input of 5 integers and saving it to an array. This data is then written to a pipe. The child process then will read the data from the pie and print it out to the screen.
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#define INPUT 5
int main() {
int fd[2];
pid_t childprocess;
if((childprocess = fork()) < 0) {
perror("Cannot fork child");
}
if(childprocess > 0) {
// Parent
int userInput[INPUT];
close(fd[0]);
for(int i = 0; i < INPUT; i++) {
printf("Enter number %d: ", i+1);
scanf("%d", &userInput[i]);
}
write(fd[1], userInput, sizeof(userInput) + 1);
} else {
// Child
close(fd[1]);
int parentData[INPUT];
read(fd[0], parentData, sizeof(parentData));
for(int i = 0; i < INPUT; i++) {
printf("%d => %d", i+1, parentData[i]);
}
}
return 0;
}
When I run the program using ./a.out I observe the following behavior.
Enter number 1: 1 => -4731629522 => 327663 => 2005319684 => 15 => 1
Is there any mistake in the way pipe is implemented that causes this behavior?
The problem is that the filedescriptors are not initialized by the pipe-function. When the read-function is reached, fd[0]
is probably an invalid file descriptor. 0 bytes are read, the integers, which are written to stdout are just what was in the uninitialized array parentData
.
Just add:
pipe(fd);
How does the synchronization work?
When the read
function is called with a valid filedescriptor, the kernel halts/blocks the process and waits until the requested amount of bytes (sizeof parentData
) is written to the pipe by the other process. Then the kernel copies the bytes from the pipe. This is called blocking IO.
Note: when the writing process stops/closes the filedescriptor before the requested amount of bytes is reached, not all bytes are written to the buffer. The return value of read
is the amount of read bytes.
There is also nonblocking IO. The process can do other things while waiting for the data. It is often implemented with a thread, which reads (with blocking IO) from the filedescriptor/socket(network IO) and sets a flag when finished.