Description of the six-week process and creation of the process by 20135217 Sun Xiaobo this week's main content:
- How to describe a process: the data structure of a process descriptor;
- How to create a process: how the kernel executes, and where the newly created process begins to execute;
- Use GDB to track the process of creating a new process.
Description of the process
The three main functions of the operating system:
- Process management (most core and most basic)
- Memory management
- File system
Process Descriptor TASK_STRUCT Data structure
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 data structures are huge.
Status of the process: the state of the Linux process (ready state, run state, blocking state) differs from the process state described in the operating system principle, such as the readiness state and the running state are task_running, and when a process is task_running, it can be run, As to whether there is a difference between running it is not to get the use of CPU.
Process-marked PID: Used to mark the process
-
Process Descriptor TASK_STRUCT data structure
struct task_struct {volatile long state; /* process running state -1 unrunnable, 0 runnable, >0 stopped */void *stack; /* specifies the kernel stack of the process */atomic_t usage; unsigned int flags; /* each process identifier */unsigned int Ptrace int on_rq;/run queue and process scheduling related/
Chain List of process scheduling
All process linked list struct list_head tasks;
struct list_head{ struct list_head *next,*prev;};
The implementation of a two-way circular linked list of cores: a more abbreviated two-way loop linked list.
Address space memory management related to processes
struct mm_struct *mm, *active_mm;
Process Indication (PID)
pid_t pid;pid_t tgid;
Process Parent-child relationship
A process created by a program has a parent-child relationship, and it is often necessary to refer to such a parent-child relationship when programming. There are several fields in the process descriptor that are used to represent such relationships
struct task_struct __rcu *real_parent; /* Real parent Process */struct task_struct __rcu *parent; /* recipient of SIGCHLD, WAIT4 () reports */struct list_head children; /* List of my children */struct list_head sibling; /* linkage in my parent ' s children list */struct task_struct * Group_leader; /* threadgroup leader */
Debugging
struct list_head ptraced;struct list_head ptrace_entry;
Current task-related CPU state
struct thread_struct thread;
Linux allocates a 8KB-sized memory area for each process to hold two different data structures for the process: thread_info and process kernel stacks
Creation of process creation process
The start _ Kernel code in Rest _ init creates two kernel threads, kernel _ init and kthreadd. Kernel _ init starts the user-state process init, which is the ancestor of all user-state processes, and Kthreadd is the ancestor of all kernel threads.
The principle of creating a process and starting the kernel at the command line is roughly the same, copying a No. 0 process descriptor, and then completing the process creation based on the process's need to modify the data structure such as the PID.
Fork the user-state code of a process
#Include<stdio.h>#Include<stdlib.h>#Include<unistd.h>IntMain(int argc,char * argv[]) {int pid;/* Fork Another process */pid = fork ();Fork is a system call that is used to create a child process in the user stateif (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 child to complete*/wait (null); printf ( "child complete!\n");}
The fork system call is returned once in the parent and child processes, the PID returned in the child process is 0, the PID of the return value subprocess in the parent process, so that the else if (pid==0) and else in the program are executed, and there are two processes behind it, which can be used to create child processes in the user state.
To create a new process in the kernel execution process
System Call review: see section Fourth blog http://www.cnblogs.com/July0207/p/5277774.html
Fork, Vfork, and clone three system calls can create a new process, and all are created by calling Do_fork to implement the process
Linux creates a new process by copying the parent process, and most of the information is the same, and a small number of information needs to be modified, or chaos will occur. For example: PID, process list, kernel stack, process execution context thread, etc., and set the next instruction returned by fork (ESP and EIP). This gives a general framework for process creation:
Copy a pcb--task_struct
p = dup_task_struct(current);//复制进程的PCBint __weak arch_dup_task_struct(struct task_struct *dst,struct task_struct *src){ *dst = *src;//通过赋值实现复制 return 0;}
Assigning a new kernel stack to a new process
ti = alloc_thread_info_node(tsk, node);tsk->stack = ti;setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈
Modify the copied process data, such as PID, process chain list, etc. (see copy_process inside).
/*copy_thread in copy_process*//*拷贝内核堆栈数据和指定新进程的第一条指令地址*/*childregs = *current_pt_regs(); //复制内核堆栈,只复制了SAVE_ALL相关的部分childregs->ax = 0; //子进程的fork返回0的原因p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址
Where the new process that is created starts
The int instruction and save_all the contents of the kernel stack: the related data structure of the system call stack, the system call number, the Register parameter.
When the sub-process gets control of the CPU, the RET _ form fork can stack the stack from the Iret back to the user state, thus switching to the user space of the child process.
Experiment--using GDB to track the process of creating a new process
Remove the menu directory and use the GIT command to clone a new menu directory.
https://github.com/mengning/menu.git
Overwrite the test.c with TEST_FORK.C and recompile footfs
mv test_fork.c test.cmake rootfs
You can see the result of the fork function running:
GDB prepares for debugging, loads the symbol table, and sets the port.
file linux-3.18.6/vmlinuxtarget remote:1234
To set breakpoints:
- Single Step Execution:
(Because here the error reason is unknown, there is no way to single-step debugging, the subsequent experiment in the experimental building environment to complete.) )
(1) Using command C to continue execution, you can see the execution to the Do_fork place
(2) Step to Copy_process
(3) After entering the DUP _ task _ struct
(4) Continue to be available to Copy_thread
(5) After tracking to ret _ form _ fork, can not continue to track execution, end debugging.
Summary: By using GDB to track the process of creating a new process, you can see that the process for creating a new process is as follows:
- First call the Do_fork function (function function is fork a new process);
- Copy _ Process function in the Do _ fork copies information about the parent process
- The PCB for the DUP task _ struct () replication process
- The thread-related code assigns a new kernel stack to the new process, and copy _ thread copies the kernel stack, copying only the parts related to save _.
- Set the top of the kernel stack when the SP is dispatched to the child process, the first instruction address when IP goes to the child process
- When the sub-process gets control of the CPU to start running, ret _ form fork can stack the back stack, return from Iret to the user state, and then switch to the user space of the child process to complete the creation of the new process.
Resources
"Original works reproduced please specify the source" "Linux kernel Analysis" MOOC course http://mooc.study.163.com/course/USTC-1000029000
Section Sixth description of the process and creation of the process