Child processes are scheduled independently of parent processes. As such, we cannot predict in what order parent and child processes will execute. We often want to have a parent process wait until one or more child processes have completed. To do so, we can use the wait family of system calls. Today, we will look at one of the these system calls – the wait() function.
The wait() function waits for any child process to die. To use wait(), we must include the sys/types.h and sys/wait.h header files.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void){
pid_t child;
int status;
if((child = fork())<0){
printf("Error in creating new process.");
return 1;
}
//in parent process
if(child>0){
//pass wait a pointer to int
wait(&status);
printf("\nThat's a lot of numbers!\n");
}
//in child process
if(child==0){
int i = 0;
while(i++ < 1000){
printf("%d", i);
}
}
return 0;
}
The wait function accepts a single argument in the form of a pointer to an int.
The wait function returns the process ID of the child process that has ended.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void){
int status;
pid_t child = fork();
if(child<0){
printf("problem forking process.\n");
return 1;
}
if(child==0){
printf("in child process.\n");
printf("process ID %d\n", getpid());
printf("parent ID %d\n", getppid());
}
if(child>0){
if(child==wait(&status)){
printf("child process %d ended.\n", child);
}
}
return 0;
}
Our next program will span multiple processes using a while loop and assign each PID to an array, which we we will use to keep track of what child processes have completed executing.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <time.h>
#define NUM_ELEMENTS 10
void removeProcess(pid_t array[], pid_t process, int size);
void printProcesses(pid_t array[], int size);
int main(void){
pid_t parentID = getpid();
pid_t childID;
pid_t IDs[NUM_ELEMENTS];
int i = 0;
int status;
int random;
while(i < NUM_ELEMENTS){
childID = fork();
if(childID==0){
printf("In child ID %d with parent ID %d\n", getpid(), getppid());
//generate random number for sleep()
srand(time(NULL)+(i*2));
random = (rand() % 15) + 1;
sleep(random + random);
//break out of the loop
break;
}
if(childID > 0){
IDs[i++] = childID;
}
}
if(parentID==getpid()){
while(i > 0){
childID = wait(&status);
printf("\nProcess %d exited.\n", childID);
//remove process from array
removeProcess(IDs, childID, NUM_ELEMENTS);
//print out remaining processes
if(i!=1){
printf("The following child processes remain active: \n");
printProcesses(IDs, NUM_ELEMENTS);
}
i--;
}
}
return 0;
}
//remove the exited process from the array
void removeProcess(pid_t array[], pid_t process, int size){
for(int i = 0; i < size; i++){
if(array[i]==process){
array[i] = 0;
return;
}
}
}
//print the remaining active processes
void printProcesses(pid_t array[], int size){
for(int i = 0; i < size; i++){
if(array[i]!=0){
printf("%d\t", array[i]);
}
}
putchar('\n');
}
Next time we will cover waitpid() as well as interpreting the exit status of child processes.
Be sure and check out my author page on Amazon.com at http://www.amazon.com/Al-Jensen/e/B008MN382O/