Process Management using wait and exit

Table of Content

Table of Contents

Process Management using wait and exit

Exit() System Call

The exit() function is how a process tells the operating system that it’s finished and ready to be removed. When a process uses exit(), it can also send some final information back to its parent process. The parent can then collect this information using the wait() function.

				
					#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    printf("This program will exit in 3 seconds\n");
    sleep(3);
    printf("Exiting now\n");
    exit(0);
    // The following line will never be executed
    printf("This line is after exit()\n");
}
				
			

Wait() System Call

  • The wait() function is a way for a parent process to pause and wait for one of its child processes to finish. When a child process ends, the parent process can continue its work.
  • A child process can end in different ways: by calling exit(), returning from main, or receiving a signal that tells it to stop.
  • The wait() function is useful because it helps coordinate the activities of parent and child processes, ensuring that the parent doesn’t continue until the child has completed its task.

Behavior of Wait()

  • When a parent process uses wait(), it will pause until any of its child processes finishes. If a child process ends, wait() tells the parent which child (by its ID number) has finished.
  • If more than one child process ends at the same time, wait() will choose one of them randomly to report back. If the parent doesn’t have any child processes when it calls wait(), the function immediately returns with a special signal (-1) to indicate that there are no children to wait for.
  • WIFEXITED: Wait If EXITED

    • This macro checks if the child process terminated normally (i.e., via an exit() call or a return from main()).
  • WEXITSTATUS: Wait EXIT STATUS

    • This macro extracts the exit status of the child process if WIFEXITED is true.
				
					#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    pid_t child_pid = fork();

    if (child_pid == 0) {
        // Child process
        printf("Child process is running\n");
        sleep(2);
        exit(5);
    } else if (child_pid > 0) {
        // Parent process
        int status;
        wait(&status);
        if (WIFEXITED(status)) {
            printf("Child process exited with status %d\n", WEXITSTATUS(status));
        }
    } else {
        // Fork failed
        fprintf(stderr, "Fork failed\n");
        return 1;
    }

    return 0;
}
				
			

Explanation: 

  • If fork() returns 0, the code inside the if (child_pid == 0) block is executed by the child process. The child process prints a message, pauses for 2 seconds using sleep(2), and then exits with a status of 5.

  • If fork() returns a positive number, the parent process executes the code in the else if (child_pid > 0) block. The parent waits for the child process to finish using wait(). Once the child process terminates, the parent checks if it ended normally using WIFEXITED(status). If true, the parent retrieves and prints the child’s exit status using WEXITSTATUS(status).

  • If fork() fails, the code in the else block runs, printing an error message and returning 1 to indicate the failure.

execlp() System Call

  • The execlp() function is used to replace the current process with a new program. It’s often used after creating a new process with fork().
  • When you use execlp(), it loads a new program into memory, erasing the current program, and starts running the new one.
  • This is useful when you want a child process to run a different program than its parent.
				
					#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

void main(void) {
  pid_t pid = 0;
  int status;
  pid = fork();

if (pid == 0) {
  printf("I am the child.");
  execl("/bin/ls", "ls", "-l", "/home/ubuntu/", NULL);
  perror("In exec(): ");
}

if (pid > 0) {
  printf("I am the parent, and my pid is %d.\n", pid);
  wait(&status);
  printf("End of process %d: ", pid);

}

if (pid < 0) {
  perror("In fork():");
}

exit(0);
}
				
			

Zombies Processes

When a process finishes but its parent hasn’t yet used wait() to acknowledge its end, it becomes a “zombie” process. A zombie is a process that has finished running but still uses a small amount of system resources. The parent process is responsible for “reaping” its zombie children by using wait() to collect their exit information. Once this is done, the operating system can fully remove the child process from its records.

				
					#include <stdlib.h> 
#include <sys/types.h> 
#include <unistd.h> 
int main() 
{ 
    // Fork returns process id 
    // in parent process 
    pid_t child_pid = fork(); 
  
    // Parent process  
    if (child_pid > 0) 
        sleep(50); 
  
    // Child process 
    else        
        exit(0); 
  
    return 0; 
}