Detailed usage of subprocess recycling functions wait and waitpid

Posted by Mykasoda on Tue, 08 Feb 2022 11:13:38 +0100

Subprocess recycling

0. Background

When the process terminates, it will close all file descriptors and release the memory allocated in the user area, but the process control block (PCB) of the process in the kernel area is still reserved to save some information.

  • If the program exits normally, what is saved in the PCB is the exit state (parameter of exit() function).

  • If the program exits abnormally, the signal saved in the PCB is the signal that causes the program to terminate.

  • The * * parent process of the process can call the wait and waitpid functions to obtain the information saved in the PCB * * and completely clear the process.

1. wait function

1.1 function prototype

#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status)

1.2 function

The parent process can call the wait function to obtain the termination information of the child process and completely clear the child process. The specific functions are as follows:

  • Block the parent process and wait for the child process to exit
  • Get subprocess exit status information
  • Reclaim child process resources

1.3 function parameters

  • @param: status is an outgoing parameter. The variable should be defined and then passed into the variable address. The function can send out the information in the sub process PCB through this parameter. See section 1.5 for details.

1.4 function return value

  • Success: returns the process ID of the terminated child process
  • Failure: Return - 1

1.5 use the macro to obtain the status information carried by the outgoing parameters

If the argument of the wait function is not NULL, but the argument pointer of int, the wait function will send out the child process status information through the argument, and the information carried by the parameter can be known through the macro provided by the system.

  • Wired (status): if the subprocess is through the following: exit() function_ Exit(), main function return mode ends normally, and the macro returns true. Next, you can get the exit status of the process (that is, the parameter of the exit() function) through the WEXITSTATUS(status) macro.
  • Wifsignled (status): if the macro returns true, the subprocess exits abnormally. The abnormal exit of the program is mainly due to the signal. Next, the number of the signal that caused the process to terminate can be obtained through WTERMSIG(status).
  • WIFSTOPPED(status): if the process is suspended, the macro returns true. Next, WSTOPSIG(status) can be used to get the number of the signal that caused the process to pause. If WIFCONTINUED(status) is true, the process has started running after being suspended.

1.6 code example

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h> // exit

int main(void)
{
    pid_t pid = fork();
    int status = 0;
    if (pid > 0) {
        pid_t wpid = wait(&status);
        if (WIFEXITED(status))
        {
            // Normal exit
            printf("I'm parent, The child process "
					"%d exit normally\n", wpid);
			printf("return value:%d\n", WEXITSTATUS(status));   // WEXITSTATUS can obtain the process exit status (the parameter of exit)
            
        } else if (WIFSIGNALED(status)) {
            // The abnormal exit signal is true
            printf("The child process exit abnormally, "
					"killed by signal %d\n", WTERMSIG(status));//Get signal number
			
            // The other terminal can send kill signal with kill -9 pid						
        }
        
    } else if (pid == 0) {
        printf("I am child, my id is:%d\tmy parent id is:%d\n.",getpid(), getppid());
        sleep(2);
    #if 0
        execl("05_abnormal", "05_abnormal", NULL);  // Signal No. 8 will be triggered because the program executed will have a division by zero error
        perror("execl error...");
        exit(-1);
    #endif
        exit(10);
    }
}

2. waitpid function

2.1 function prototype

#include <sys/types.h>
#include <sys/wait.h>

pid_t waitpid(pid_t pid, int *status, int options)

2.2 function

Like the wait function, the waitpid function is also used to reclaim the sub process resources and obtain the end state information of the sub process.

2.3 function parameters

  • @param: pid:
    • >0: Reclaim child process with specified ID
    • -1: Reclaim any child process. waitpid(-1, status, 0) is equivalent to wait(status)
    • 0: recovery and all subprocesses of a group that currently calls the waitpid function.
    • < - 1: Reclaim any child process in the specified process group
  • @param: status: is an outgoing parameter. The variable should be defined and then passed into the variable address. The function can send out the information in the sub process PCB through this parameter.
  • @param: options:
    • 0: set to the blocking state. The blocking waits for the child process to end and recycle it.
    • WNOHSNG: set to non blocking status. If no child process ends, it will be returned directly. This parameter needs to be used in conjunction with the polling method.

2.4 function return value

  • Success: returns the process ID of the terminated child process
  • Failure: Return - 1

2.5 use macros to obtain the status information carried by outgoing parameters

Same as section 1.5 above

2.6 code examples

#include <sys/stat.h>   // waitpid
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main(void)
{
    pid_t cpid, wpid;
    int status;
    int n = 5;
    int i;
    for (i = 0; i < n; i++) {
       cpid = fork();
        if (cpid == -1) {
            perror("fork");
            exit(EXIT_FAILURE);
        } else if (cpid == 0) {
           break;
        } 
    }
    if (n == i) {
        // parent
        sleep(n);
        printf("I am parent, pid is: %d.\n", getpid());
        do
        {
           wpid = waitpid(-1, NULL, WNOHANG);
           if (wpid > 0) {
               n--;
           }
           sleep(1);
        } while (n > 0);
       printf("wait finished.\n");
       
    } else {
        sleep(i);
		printf("I'm %dth child, pid = %d\n", i+1, getpid());
    }

}