The only thing you should remember is that when you fork , the parent and child will continue to work with the code at this point.
So, if you do not correctly define the definition of child / parent, children will most likely launch their own children.
A good way to run three children without grandchildren is to use a counter in conjunction with the returned process id from the fork call according to the following lines:
#include <stdio.h> #include <unistd.h> #define COUNT 3 int main(void) { # Desired and actual count. int count = COUNT, children = 0; // Force parent initially. pid_t retpid = 1; // Only fork if limit not reached AND is parent (children // will exit loop with retpid == 0). while (count-- > 0 && retpid > 0) // Adjust actual count if successful. if ((retpid = fork()) > 0) children++; // Detect parent, all forks returned non-zero. if (retpid != 0) { printf("Parent %d spawned %d/%d children\n", getpid(), children, COUNT); // Wait for children to finish. while (children-- > 0) wait(NULL); } else { // Otherwise you were one of the children. printf("Child %d, sired by %d\n", getpid(), getppid()); } return 0; }
This displays what you think, although, due to the vagaries of planning, it is not necessary in this order:
Parent 26210 successfully spawned 3/3 children Child 26212, sired by 26210 Child 26213, sired by 26210 Child 26211, sired by 26210
Checking the returned PID code ensures that only the parent performs any fork, and the account will limit it to a certain value.
One thing you also need to keep an eye on is output buffering. When you use fork, you can get two processes with buffered output.
If the output device can be detected as a terminal, flushing will run normally on the output of a new line, so your printf calls will probably not duplicate the output for a normal run.
You just need to know that you can get interesting results if you redirect your output to a file, for example.