If the parent process exits before the child process, there must be a mechanism to ensure that the child process can find a new parent, otherwise these orphaned processes will always be in a zombie state at the time of the exit, wasting memory for nothing. Zombie State is the call to the Do_exit () function, the last call to the Exit_notify () function to send a signal to the parent process, the child process to find the adoptive father, the adoptive father for the thread group of other threads or the init process, and the process (stored in the task_struct structure of the Exit_ State) is set to Exit_zombie. For this problem, the workaround is to have the child process find a thread within the current thread group as the father, and if not, let Init do their parent process. Exit_notify () is called in Do_exit (), which calls Forget_original_parent () and the latter invokes Find_new_reaper () to perform the parent-seeking process:
Understanding Forget_original_parent () requires the following basic knowledge:forget_original_parent () is defined in:linux/kernel/exit.c
1 child process of parent = = Real_parent
This is a subprocess of this process and is not being ptrace on the children list of this process.
2 Parent = = Father && Parent! = Real_parent Child process
The child process of other processes ptrace by this process is on the children list of this process.
3 Real_parent = = Father && Parent! = Real_parent Child process
The child process of this process, but is being ptrace by other processes, on the Ptrace_children list of this process.
/* * When we die, we re-parent all our children. * Try to give them to another thread in we thread * group, and if no such member exists, give it to * the Child Reaper PR Ocess (ie "init") in our PID * space. */static struct task_struct *find_new_reaper (struct task_struct *father) {struct Pid_namespace *pid_ns = task_active_pid _ns (father); struct task_struct *thread;thread = father;while_each_thread (father, thread) {/////traverse the end of the process to the next process in the thread group if ( Thread->flags & pf_exiting) <span style= "Font-family:verdana;" >continue;</span>
<span style= "White-space:pre" ></span>//if the resulting next process is marked pf_exiting, it does not meet the requirements and needs to continue traversing
& The Lt;span style= "White-space:pre" ></span>//task_struct struct has a flags flag that represents the current state of the process
<span style= "White-space:pre" ></span>//<span style= "Font-family:verdana;" >pf_starting:<span style= "Color:rgb (17, 17, 17); Font-family:verdana; font-size:14.44444465637207px; line-height:23.99305534362793px; " > Whether the process is being created <span style= "Color:rgb (17, 17, 17); Font-family:verdana; font-size:14.44444465637207px; line-height:23.99305534362793px; " >pf_exiting: Process exits <span style= "Color:rgb (17, 17, 17); Font-family:verdana; font-size:14.44444465637207px; line-height:23.99305534362793px; " >pf_memalloc:<span style= "Color:rgb (17, 17, 17); Font-family:verdana; font-size:14.44444465637207px; line-height:23.99305534362793px; " > is currently allocating memory </span></span></span></span></span>if (unlikely (pid_ns->child_ Reaper = = father))//unlikely if the same process returns true/*child_reaper the role is in the current thread group if the adoptive father is not found, after the end of the managed presentation process is required, this child_ The process that the Reaper points to hosts the end process, one of which is to reclaim the orphan process. If the managed process is the end process itself, the managed process needs to be reset, which is to set the managed process as the adoptive process thread of the current process. */pid_ns->child_reaper= Thread;return thread;//finds a process that meets the requirements in the thread group where the end process is located, returns the}/* if there are no other processes in the same thread group as the end process, the function returns the Child_reaper of the namespace where the end process resides. The managed process pointed to (provided that the managed process is not the end process itself) */if (unlikely (pid_ns->child_reaper = = father)) {/* If the end process is in the namespace of Child_reaper The managed process that points to is the end process itself, and the program runs to this point, stating that the required process has not been found in the thread group, and that the managed process needs to be set to the INIT process for the function to return */WRITE_UNLOCK_IRQ (&tasklist_lock); if (unlikely (Pid_ns = = &init_pid_ns))//If the INIT process needs to give the Error,init process cannot terminate panic ("Attempted to kill init!"); Zap_pid_ns_processes (Pid_ns); Write_lock_irq (&tasklist_lock);/* * We can not clear->child_reaper or leave it Alone. * There stealth exit_dead tasks on->children, * forget_original_parent () must move them somewhere. */pid_ns->child_reaper = init_pid_ns.child_reaper;//Sets the hosting process for the current process space to the managed process of the INIT process}return Pid_ns->child_reaper ;//Returns the managed process found is the adoptive father process}
Reaper = Find_new_reaper (father);//The adoptive process is found in this function, either the other processes within the thread group, or the INIT process, and finally the process descriptor deletion is handled by the adoptive process, if the parent process exits first, The process has become an orphan process.
<span style= "Color:rgb (51, 51, 51); font-family:arial; font-size:14px; line-height:26px; text-align:justify; " > After you find the appropriate new parent process for the child process, you need to set a new parent process for all child processes of the process </span><span style= "color: #111111;" >list_for_each_entry_safe (P, N, &father->children, sibling) {</span><span style= "Color:rgb (17, 17 , 17); White-space:pre; " ></span><span style= "color: #111111;" >p->real_parent = Reaper;</span><span style= "Color:rgb (17, 17, 17); White-space:pre; " ></span><span style= "color: #111111;" >if (p->parent = = father) {</span><pre name= "code" class= "CPP" style= "FONT-SIZE:14.44444465637207PX; line-height:23.99305534362793px; " ><span style= "color: #111111;" >//</span><span style= "font-family: blackbody; font-size:12px; line-height:26px; Background-color:rgb (255, 255, 255); " > The thread that is currently exiting is not its true father, so it is bound to be a tracked process. Otherwise, the system log printing error </span>
bug_on (Task_ptrace (P));
<span style= "WHITE-SPACE:PRE;" ></span> <span style= "font-size:12px; font-family:arial, Helvetica, Sans-serif;" > </span><span style= "font-size:12px; Font-family:arial, Helvetica, Sans-serif; >p->parent =</span><span style= "FONT-SIZE:12PX; Font-family:arial, Helvetica, Sans-serif; > P->real_parent;</span><span style= "font-size:12px; Font-family:arial, Helvetica, Sans-serif; ></span>//to set the parent process of the current process as the true parent process
<span style= "Color:rgb (+, +); font-family:verdana; font-size:14px; line-height : 24px; White-space:pre; " ></span><span style= "Font-family:verdana;color: #111111;" ><span style= "FONT-SIZE:14PX; line-height:24px; " >}</span></span><span style= "Color:rgb (17, 17, 17); Font-family:verdana; font-size:14px; line-height:24px; White-space:pre; " ></span><span style= "Font-family:verdana;color: #111111;" ><span style= "FONT-SIZE:14PX; line-height:24px; " >reparent_thread (father, p, &dead_children); </span></span><span style= "Color:rgb (17, 17, 17); Font-family:verdana; font-size:14px; line-height:24px; White-space:pre; " ></span><span style= "Font-family:verdana;color: #111111;" ><span style= "FONT-SIZE:14PX; line-height:24px; " >}</span></span>
Finally call the Exit_ptrace () function to find the father for the Ptrace child process
Orphan Process Exit analysis