【Linux】Zombies and Orphans&& Process Waiting

Table of contents

1. Zombie process

1. Zombie process

2. The harm of zombie processes

2. Orphan process

1. Orphan process

3. Process waiting

1. The necessity of process waiting

2. wait method

3. waitpid method

4. Recycling summary


1. Zombie process

1. Zombie process

Zombies are a rather special state.

When the process exits and the parent process (using the wait() system call, discussed later) does not read the return code of the child process exit, a zombie (zombie) process will occur. The zombie process will remain in the process table in a terminated state, and will Waiting for the parent process to read the exit status code.

Therefore, as long as the child process exits, the parent process is still running, but the parent process does not read the child process status, and the child process enters the Z state.

Let’s take an example of creating a zombie process that lasts for 30 seconds:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	pid_t id = fork();
	if (id < 0) {
		perror("fork");
		return 1;
	}
	else if (id > 0) { //parent
		printf("parent[%d] is sleeping...\n", getpid());
		sleep(30);
	}
	else {
		printf("child[%d] is begin Z...\n", getpid());
		sleep(5);
		exit(EXIT_SUCCESS);
	}
	return 0;
}

When the fork() function returns a value, the parent process and the child process are started at the same time. When the child process finishes running and exits the process, the parent process is still waiting. At this time, the child process has been waiting for the parent process to read its exit status code, thus creating a zombie. state;

Zombies can cause memory leaks, and we should avoid them as much as possible;

2. The harm of zombie processes

The exit status of the process must be maintained, because it needs to tell the process that cares about it (the parent process) how well I did the task you gave me. But if the parent process never reads, then the child process will always be in Z state? Yes!

Maintaining the exit status itself requires data maintenance, and it is also the basic information of the process, so it is stored in task_struct (PCB). In other words, the Z state will never exit, and the PCB will always need to be maintained? Yes!

Which parent process creates many child processes but does not recycle them? Will this cause a waste of memory resources? Yes! Because the data structure object itself takes up memory, think about defining a structure variable (object) in C to open up space somewhere in the memory!

Memory leak? Yes!

2. Orphan process

1. Orphan process

If the parent process exits early, then the child process exits later and enters Z. What should be done?

If the parent process exits first, the child process is called an "orphan process".

The orphan process is adopted by init process No. 1. Of course, it must be recycled by the init process.

Let’s write a process to get a feel for it:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
	pid_t id = fork();
	if (id < 0) {
		perror("fork");
		return 1;
	}
	else if (id == 0) {//child
		printf("I am child, pid : %d\n", getpid());
		sleep(10);
	}
	else {//parent
		printf("I am parent, pid: %d\n", getpid());
		sleep(3);
		exit(0);
	}
	return 0;
}

After the fork() function returns, the child process and the parent process run at the same time. When the parent process finishes execution and exits, the child process is still running. At this time, the child process becomes an orphan!

Generally, the orphan process will eventually be adopted by init process No. 1, which will not cause memory leaks;

3. Process waiting

1. The necessity of process waiting

As mentioned before, if the child process exits and the parent process is ignored, it may cause a 'zombie process' problem, which in turn may cause a memory leak.

In addition, once the process becomes a zombie state, it will be invulnerable, and the "kill without blinking" kill -9 is useless, because no one can kill a dead process.

Finally, we need to know how well the tasks assigned by the parent process to the child process are completed. If the child process is completed, the result is correct or incorrect, or whether it exits normally.

The parent process recycles the resources of the child process and obtains the exit information of the child process through process waiting.

2. wait method

pid_t wait(int*status);

Return value: Returns the pid of the process being waited for on success, and -1 on failure.

Parameters: Output parameters, to obtain the exit status of the child process. If you don’t care, you can set it to NULL.

#include <stdio. h>
#include <unistd.h>
#include <stdlib.h>
#include<sys/types.h>
#include<sys / wait.h>
int main()
{
	pid_t id = fork();
	if (id < 0) {
		perror("fork");
		return 1;
	}
	else if (id == 0) {
		//parent
		printf("child[%d] is sleeping...\n", getpid());
		sleep(5);
		exit(3);
	}
	int status = 0;
	pid_t rid = wait(&status);
	if (rid > 0)
	{
		printf("parent[%d] is begin Z...\n", rid);
		sleep(10);
	}
	else 
	{
		printf("进程失败:rid:%d\n", rid);
	}
		return 0;
	}

In this way, wait will automatically recycle child processes in time, without forming zombies or causing memory leaks;

3. waitpid method

pid_ t waitpid(pid_t pid, int *status, int options);

Return value: When returning normally, waitpid returns the collected process ID of the child process;

If option WNOHANG is set and waitpid finds that there are no exited child processes to collect during the call, 0 will be returned;

If an error occurs during the call, -1 is returned, and errno will be set to the corresponding value to indicate the error;

parameter:

pid: Pid=-1, wait for any child process. Equivalent to wait. Pid>0. Wait for the child process whose process ID is equal to pid. status: WIFEXITED(status):

True if it is the status returned by the normal termination of the child process.

(Check whether the process exited normally) WEXITSTATUS(status): If WIFEXITED is non-zero, extract the child process exit code. (View the exit code of the process) options: WNOHANG:

If the child process specified by pid has not ended, the waitpid() function returns 0 and does not wait. If it ends normally, the ID of the child process is returned.

#include <stdio. h>
#include <unistd.h>
#include <stdlib.h>
#include<sys/types.h>
#include<sys / wait.h>
int main()
{
	pid_t id = fork();
	if (id < 0) {
		perror("fork");
		return 1;
	}
	else if (id == 0) {
		//parent
		printf("child[%d] is sleeping...\n", getpid());
		sleep(5);
		exit(3);
	}
	int status = 0;
	pid_ t rid = waitpid(-1,&status,0);
	if (rid > 0)
	{
		printf("parent[%d] is begin Z...\n", rid);
		sleep(10);
	}
	else 
	{
		printf("进程失败:rid:%d\n", rid);
	}
		return 0;
	}

4. Recycling summary

If the child process has exited, when wait/waitpid is called, wait/waitpid will return immediately, release resources, and obtain the child process exit information.

If wait/waitpid is called at any time and the child process exists and is running normally, the process may be blocked.

If the child process does not exist, an error is returned immediately.

Guess you like

Origin blog.csdn.net/m0_71676870/article/details/135181736