When you fork()
, the parent and child process will run in parallel immediately from the place where you fork()
.
time parent child
| |
| |
| fork()--------+
| | |
V | |
There is no way of telling which one of them that does something before the other - unless you synchronize their actions in some way.
To do proper synchronization between processes you can use semaphores or some other interprocess communication technique. For this simple case, you could use the old self-pipe trick.
- Create a
pipe
- When a child is created, close the writing end of the
pipe
in the child - and try reading a byte from the pipe
. This will hang until there is a byte or the pipe
is closed.
- When all children have been created, close the reading end in the parent.
- The state at this point should be:
- The parent only has the write end of the
pipe
open.
- All the children only have the read end of the
pipe
open, eagerly waiting for something to happen in the pipe
.
- When the parent want all the children to start working, close the write end of the
pipe
in the parent. This will cause the read
operation in all the children to unblock.
There's no error checking in this below, but it'll show the idea:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
enum { P_RD, P_WR }; // pipe indices, 0 and 1
int main() {
pid_t pid;
int pip[2];
pipe(pip); // create a pipe from pip[P_WR] to pip[P_RD]
for(int i = 0; i < 5; i++) {
pid = fork();
if(pid == -1) {
perror("Error\n");
exit(1);
} else if(pid == 0) {
close(pip[P_WR]); // close write end of pipe
char ch; // dummy buffer
read(pip[P_RD], &ch, 1); // hang here until closed
close(pip[P_RD]); // close read end of pipe
printf("I'm the child --> %d \n", getpid());
exit(0);
}
}
close(pip[P_RD]); // close read end of pipe
// The state at this point:
// * The parent only has the write end of the pipe open.
// * All the children only have the read end of the pipe open.
printf("I'm the parent --> %d\n", getpid());
close(pip[P_WR]); // close write end of pipe to start children
int wstatus;
while((pid = wait(&wstatus)) != -1) {
printf("%d died\n", pid);
}
}