Let's start with what's wrong with your current code:
You are not separating parent/child code by explicitly terminating the children when needed. Each child in your code will continue executing the for loop and then the code after it doing the wait(), which should only be executed by the parent.
You are not waiting for all the children. If you create 3 children, then 3 wait() calls will need to be made, one for each child. In your case the order doesn't really matter, so you can use wait() instead of waitpid()/wait3()/wait4(), but you'll need another loop.
You are not checking for errors on any of the functions you use. You definitely should!
I'm kind of missing the point of your var variable, if the intent is to just avoid entering the loop body in the child code, then a simple break, exit() or return will suffice.
A correct version of your code would be the following:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
int main() {
unsigned i;
int status;
pid_t child_pid;
printf("I am the Parent, my PID: %d\n", getpid());
for (i = 0; i < 3; i++) {
child_pid = fork();
if (child_pid == -1) {
perror("fork() failed");
return 1;
} else if (child_pid == 0) {
printf("Child: PID: %d; PPID: %d\n", getpid(), getppid() );
sleep(3);
printf("Child %d says bye!\n", getpid());
return 0;
}
}
for (i = 0; i < 3; i++) {
child_pid = wait(&status);
if (child_pid == -1) {
perror("wait() failed");
return 1;
}
if (WIFEXITED(status)) {
printf("Child %d exited with code %d\n", child_pid, WEXITSTATUS(status));
} else {
// Handle other cases here like WIFSIGNALED, WIFSTOPPED, etc...
// See `man 2 wait` for more information.
}
}
return 0;
}
how do I show/proof that all processes can exist at same time?
This can be done in a lot of different ways. You could do this externally on another terminal by using programs like ps after the 3 child are spawned (maybe increase the sleep to 10 seconds to have more time):
$ ps --ppid 249626 # get this from the output of your program
PID TTY TIME CMD
249627 pts/1 00:00:00 test
249628 pts/1 00:00:00 test
249629 pts/1 00:00:00 test
Or you could do this by printing the time of start and end of execution within your program in the children code:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <time.h>
void print_time(void) {
time_t t;
struct tm *local;
const char *local_str;
t = time(NULL);
if (t == (time_t)-1) {
perror("time() failed");
return;
}
local = localtime(&t)
if (local == NULL) {
perror("localtime() failed");
return;
}
local_str = asctime(&local);
if (local_str == NULL) {
perror("asctime() failed");
return;
}
ptintf("Child %d time: %s\n", getpid(), local_str);
}
// ... same code as before ...
} else if (child_pid == 0) {
printf("Child %d PPID: %d\n", getpid(), getppid() );
print_time();
sleep(3);
printf("Child %d says bye!\n", getpid());
print_time();
return 0;
}
// ... same code as before ...
Output:
I am the Parent, my PID: 250469
Child 250470 PPID: 250469
Child 250471 PPID: 250469
Child 250470 time: Tue Oct 26 23:53:03 2021
Child 250472 PPID: 250469
Child 250471 time: Tue Oct 26 23:53:03 2021
Child 250472 time: Tue Oct 26 23:53:03 2021
Child 250470 says bye!
Child 250470 time: Tue Oct 26 23:53:06 2021
Child 250471 says bye!
Child 250471 time: Tue Oct 26 23:53:06 2021
Child 250472 says bye!
Child 250472 time: Tue Oct 26 23:53:06 2021
Child 250470 exited with code 0
Child 250471 exited with code 0
Child 250472 exited with code 0
waitorwaitpidthree times. - kaylumexitorreturnin the child process code block to stop it executing the code after theforkthat is meant to be only for the parent. - kaylum