Analyzing the process of creating a new process for the Linux kernel

Source: Internet
Author: User

First, the principle analysis

1. Description of the process

Process Control block pcb--task_struct, in order to manage processes, the kernel must have a clear description of each process, and the process descriptor provides the process information that the kernel needs to understand.

 struct   task_struct{ volatile  long  State; //     process state, 1 means no execution, 0 means executable, and greater than 1 means stop  void  *stack; //  kernel stack      atomic_t usage; unsigned  int  flags; //  process identifier  unsigned int   Ptrace; ...}  

2. Creation of processes
Daosh One (Start_ kernel...cpu_ idle), Life Two (Kernel_ init and Kthreadd), second born three (i.e. the preceding 0, 1, 23 processes), Sansheng everything (1th process is the ancestor of all user-state processes, the 2nd process is the ancestor of all kernel threads)
Start_ kernel created cpu_ idle, which is process No. 0. And the No. 0 process created two threads, one is Kernel_ init, that is, process 1th, the process eventually started the user state, the other is Kthreadd. Process number No. 0 is a fixed code, process 1th is made by copying the No. 0 process PCB After the modification obtained on this basis.
Iret corresponds to the int 0x80 directive, one is the pop-up register value, and the other is the value of the press-in register.
If the system call is analogous to fork (), then it is equivalent to a system call that creates a child process, and then the child process returns and then runs in the kernel state while returning to the parent process and still running in the user state.

The creation process in Linux has a total of three functions: fork, create subprocess vfork, similar to fork, but parent-child processes share address space, and child processes run before the parent process. Clone, which is used primarily to create threads. All process creation in Linux is based on replication, and Linux creates a new process by copying the parent process, which is done by calling Do_ fork. Then do some special processing on the sub-process. Threads in Linux are a special kind of process. Based on the analysis of the code, Do_ Fork, Copy_ process pipeline running preparation, Wake_ Up_ new_ task as a child process forking completion. The most important feature of the fork () function is that it is called once and returns two times.

Tracking the Do_fork code

LongDo_fork (unsignedLongclone_flags, unsignedLongStack_start, unsignedLongStack_size,int__user *Parent_tidptr,int__user *child_tidptr) {    structTask_struct *p; inttrace =0; Longnr; // ...        //copies the process descriptor, returning a pointer to the created Task_structp =copy_process (Clone_flags, Stack_start, Stack_size, Child_tidptr, NULL, Trace); if(!Is_err (P)) {        structcompletion vfork; structPID *pid;        Trace_sched_process_fork (current, p); //remove the PID from the task structure bodyPID =get_task_pid (P, pidtype_pid); NR=PID_VNR (PID); if(Clone_flags &Clone_parent_settid) Put_user (NR, parent_tidptr); //If you are using Vfork, you must use some sort of completion mechanism to ensure that the parent process runs after        if(Clone_flags &clone_vfork) {P->vfork_done = &vfork; Init_completion (&vfork);        Get_task_struct (P); }        //adds a child process to the scheduler's queue, giving the child process a chance to get the CPUWake_up_new_task (P); // ...        //if Clone_vfork is set, the parent process is inserted into the wait queue and the parent process is suspended until the child process frees up its own memory space//ensure that the child process takes precedence over the parent process        if(Clone_flags &clone_vfork) {            if(!wait_for_vfork_done (P, &vfork))        Ptrace_event_pid (Ptrace_event_vfork_done, PID);    } put_pid (PID); } Else{nr=Ptr_err (P); }    returnnr;}

As you can see from the code above, Do_fork probably did a few things:
(1) Call copy_process, copy the current process to a sub-process, and set the context information for the child process accordingly.
(2) Initializing the completion processing information of the vfork (if it is a vfork call)
(3) Call Wake_up_new_task, the child process into the queue of the scheduler, at this time the child process can be selected by the scheduling process, to run.
(4) If it is a vfork call, you need to block the parent process and know that the child process executes exec.

3. Where does the new process of creation start?

In kernel, you can specify where the new process will start (that is, specify the line of code through the EIP register). There are similar mechanisms in fork that involve the kernel stack data state of the child process and the consistency of the SP and IP in the thread record in the Task_ struct, which is set in the Copy_ thread in copy_ process.

The copy_thread process is as follows:

(1) Get the location of the sub-process register information

(2) The THREAD.SP assignment of the child process, which is the value of the ESP register of the child process, which will run in the future.

(3) If you are creating a kernel thread, it will run in Ret_from_kernel_thread, assign the address of this code to THREAD.IP, and then prepare additional register information and exit.

(4) Copy the register information of the parent process to the child process.

(5) The EAX register value of the child process is set to 0, so the return value of the fork call in the child process is 0.

(6) The child process begins execution from Ret_from_fork, so its address is assigned to THREAD.IP, which is the future EIP register. From the above process, we see that the child process replicates the context information of the parent process, only changes in some places, the running logic and the parent process are exactly the same.

In addition, the child process starts from the ret_from_fork, and the child process is guaranteed by these places:

(1) A new stack is assigned to it in the dup_task_struct.

(2) Sched_fork is called in Copy_process and is set to task_running.

(3) Copy_thread The register context of the parent process to the child process, which is a critical step in ensuring that the stack information for the father-child process is consistent.

(4) Set the address of the ret_from_fork to the value of the EIP register, which is the first instruction of the child process.

Ii. contents of the experiment

Update menu, delete test_fork.c and test.c files, and re-execute make rootfs. First, start with QEMU, and then set a breakpoint at Sys_clone. Execute the following code:

#include <stdio.h>#include<stdlib.h>#include<unistd.h>intMainintargcChar*argv[]) {    intpid; /*Fork Another process*/PID=Fork (); if(PID <0)     {         /*error occurred*/fprintf (stderr,"Fork failed!"); Exit (-1); }     Else if(PID = =0)     {        /*Child Process*/printf ("This is the child process!\n"); }     Else     {          /*Parent Process*/printf ("This is the Parent process!\n"); /*parent would wait for the*/Wait (NULL); printf ("Child complete!\n"); }}

After the execution, came to the point where the breakpoint

Sys_clone actually call or do_fork, that is, the real process creation is the final call Do_fork, and then into the function, there is a function copy_process, which is the beginning of the detailed creation. The first is the anomaly judgment, then started the dup_task_struct, which is to replicate the parent process, producing the child process.   concrete function is

 int  __weak arch_dup_task_struct (struct  task_struct *dst,  str    UCT  task_struct *src) { *dst = *SRC;  return  0  ;}  

after the copy is finished, the child process is the same as the parent process, and the kernel stack is copied during the copy process, followed by the child process assignment

Copy files, copy file system, copy signals, etc.  then step into function copy_thread.

 p->thread.sp = (unsigned long ) Childregs; //           child process Stack address  *childregs = *current_pt_regs (); //                   Childregs->ax = 0 ; // ax Save the return value, the return value of the child process fork is 0  p->thread.ip = (unsigned long ) Ret_from_fork; //  
of the child process

and go down one step further.

Compile inside check See Fork command, get child process and parent process result.

Start GDB debugging and set breakpoints on the primary function.

Iii. Summary

where is the "special focus" on where the new process starts? Why does it go smoothly? That is, how the execution start point is consistent with the kernel stack, because ret_ from_ Fork determines the address of the first instruction of the new process. The child process starts at the ret_ From_ Fork. Because before ret_ From_ Fork, that is, in the copy_ thread () function * childregs = * Current_ pt_ regs (), this sentence assigns the regs parameter of the parent process to the kernel stack of the child process. * The Childregs type is Pt_ regs, which stores the parameters of the Save_ all in the stack, so it can be executed smoothly in the subsequent restore all.

The new process is created by cloning the old program (the current process). The fork () and Clone () (for thread) system calls can be used to establish a new process. At the end of these two system calls, the kernel allocates a new task_struct structure to the new process in the system's physical memory and allocates physical pages for the stack to be used by the new process. Linux also assigns a new process identifier to the new process. The address of the new task_struct structure is then saved in the linked list, and the TASK_STRUCT structure content of the old process is copied into the task_struct structure of the new process. When cloning a process, Linux allows two processes to share the same resources. Resources that can be shared include files, signal handlers, and virtual memory.

Liu Shuai

Original works reproduced please indicate the source

"Linux kernel Analysis" MOOC course http://mooc.study.163.com/course/USTC-1000029000

Analyzing the process of creating a new process for the Linux kernel

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.