Linux learning summary (9) recycling child process

Orphan process

If the parent process ends before the child process, the child process becomes an orphan process. The parent process of the child process is called the init process, which is called the init process to adopt the orphan process.

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

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

    if (pid == 0) {
    
    
        while (1) {
    
    
            printf("I am child, my parent pid = %d\n", getppid());
            sleep(1);
        }
    } else if (pid > 0) {
    
    
            printf("I am parent, my pid is = %d\n", getpid());
            sleep(9);
            printf("------------parent going to die------------\n");
    } else {
    
    
        perror("fork");
        return 1;
    }

    return 0;
}

Zombie process

The process is terminated, the parent process has not yet been recycled, and the remaining resources (PCB) of the child process are stored in the kernel and become a zombie process.
Special attention: zombie processes cannot be removed using the kill command, because the kill command is only used to terminate the process, and the zombie process has been terminated.

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

int main(void)
{
    
    
    pid_t pid, wpid;
    pid = fork();

    if (pid == 0) {
    
    
            printf("---child, my parent= %d, going to sleep 10s\n", getppid());
            sleep(10);
            printf("-------------child die--------------\n");
    } else if (pid > 0) {
    
    
        while (1) {
    
    
            printf("I am parent, pid = %d, myson = %d\n", getpid(), pid);
            sleep(1);
        }
    } else {
    
    
        perror("fork");
        return 1;
    }

    return 0;
}

wait function

When a process terminates, it closes all file descriptors and releases the memory allocated in user space, but its PCB is still reserved, and the kernel saves some information in it: if it terminates normally, it saves the exit status, if it terminates abnormally It holds the signal that caused the process to terminate. The parent process of this process can call wait or waitpid to obtain this information, and then completely clear the process. We know that the exit status of a process can be viewed in the Shell with the special variable $?, because the Shell is its parent process. When it terminates, the Shell calls wait or waitpid to get its exit status and clear the process completely.
The parent process calls the wait function to recover the termination information of the child process. This function has three functions:

  • Block waiting for the child process to exit
  • Recycle the remaining resources of the child process
  • Get the end status of the child process (exit reason)

pid_t wait(int *status)
success: return the ID of the child process that was cleaned up;
failure: return -1 (no child process)

When the process terminates, the operating system's implicit recycling mechanism will:

  • Close all file descriptors
  • Release the memory allocated by user space. The PCB of the kernel still exists, which saves the exit status of the process. (Normal termination→Exit value; Abnormal termination→Termination signal)

You can use the wait function to pass the parameter status to save the exit status of the process. Use the macro function to further determine the specific reason for the process termination. Macro functions can be in the following three groups:

  1. WIFEXITED(status) is non-zero → the process ends normally
    WEXITSTATUS(status) If the above macro is true, use this macro → get the process exit status (exit parameter)
  2. WIFSIGNALED(status) is non-zero → the process terminates abnormally
    WTERMSIG(status) As the above macro is true, use this macro → get the number of the signal that caused the process to terminate.
  3. WIFSTOPPED(status) is non-zero → the process is in a paused state
    WSTOPSIG(status) As the above macro is true, use this macro → to get the number of the signal that makes the process pause.
    WIFCONTINUED(status) is true → the process has continued to run after being suspended
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>

int main(void)
{
    
    
	pid_t pid, wpid;
	int status;

	pid = fork();

	if(pid == -1)
	{
    
    
		perror("fork error");
		exit(1);
	} 
	else if(pid == 0)
	{
    
    		//son
		printf("I'm process child, pid = %d\n", getpid());
#if 1
		execl("./abnor", "abnor", NULL);
		perror("execl error");
		exit(1);
#endif
		sleep(1);				
		exit(10);
	} 
	else 
	{
    
    
		//wpid = wait(NULL);	//传出参数
		wpid = wait(&status);	//传出参数

		if(WIFEXITED(status)){
    
    	//正常退出
			printf("I'm parent, The child process "
					"%d exit normally\n", wpid);
			printf("return value:%d\n", WEXITSTATUS(status));

		} 
		else if (WIFSIGNALED(status)) 
		{
    
    	//异常退出
			printf("The child process exit abnormally, "
					"killed by signal %d\n", WTERMSIG(status));
										//获取信号编号
		}
		else 
		{
    
    
			printf("other...\n");
		}
	}
	return 0;
}

waitpid function

The role is the same as wait, but you can specify the pid process to clean up without blocking.

pid_t waitpid(pid_t pid, int *status, int options);
Success: returns the ID of the cleaned up child process;
failure: returns -1 (no child process)

Special parameters and return conditions:
parameter pid:

  • >0 Recycle the child process with the specified ID
  • -1 Recycle any child process (equivalent to wait)
  • 0 Recycle and all child processes of a group currently calling waitpid
  • <-1 Recycle any child process in the specified process group

Return 0 and the third parameter is WNOHANG, indicating that the child process is running.
Note: A call to wait or waitpid can only clean up one child process. To clean up multiple child processes, a loop should be used.

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

int main(void)
{
    
    
	pid_t pid, pid2, wpid;
	int flg = 0;

	pid = fork();
	pid2 = fork();

	if(pid == -1)
	{
    
    
		perror("fork error");
		exit(1);
	} 
	else if(pid == 0)
	{
    
    		//son
		printf("I'm process child, pid = %d\n", getpid());
		sleep(5);				
		exit(4);
	} 
	else 
	{
    
    					//parent
		do 
		{
    
    
			wpid = waitpid(pid, NULL, WNOHANG);
            //wpid = wait(NULL);
			printf("---wpid = %d--------%d\n", wpid, flg++);
			if(wpid == 0)
			{
    
    
				printf("NO child exited\n");
				sleep(1);		
			}
		} while (wpid == 0);		//子进程不可回收

		if(wpid == pid)
		{
    
    		//回收了指定子进程
			printf("I'm parent, I catched child process,"
					"pid = %d\n", wpid);
		} 
		else 
		{
    
    
			printf("other...\n");
		}
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/bureau123/article/details/112064406