For more information about Kernel threads (kernel_thread)-General Linux technology-Linux programming and kernel, see the following. We know that the Linux kernel uses kernel threads to divide the kernel into several functional modules,
Like kswapd and kflushd, The init process in the system is also called by the idle process.
Kernel_thread.
Let's first look at the implementation of the kernel thread, and then analyze the nature of the kernel thread.
Int kernel_thread (int (* fn) (void * arg), void * arg, int flags)
{
Long retval, d0;/* at least two local variables */
This code is translated into an intuitive ASM code:
{
Movl _ NR_clone, % 0;/* load the clone system call number to reg */
Movl _ NR_exit, % 3;/* load the exit system call number to reg */
Movl arg, % 4;/* load the fn parameter of the function into reg */
Movl fn, % 5;/* load the fn pointer of the function into reg */
Movl flags | CLONE_VM, % ebx;/* Move flags to % ebx */
Mov % esp, % esi;/* save register % esp in % esi */
Int $0x80;/* Because % eax contains the clone system call number
Sys_clone is called.
All registers will be pushed to the stack, so the sub-process will
To obtain flags, fn ,__ NR_exit, etc.
After the return, the child process almost inherits everything from the parent process,
Our analysis of do_fork shows that the sub-process will obtain the new kernel stack,
The stack is the content of each register, and TSS is modified at the same time:
EIP = ret_from_fork,
ESP = new kernel stack bottom-sizeof (pt_regs ),
SSO =__ KERNEL_DS,
ESP0 = new kernel stack top,
(??) Modify OLDESP on the stack = new kernel stack bottom
After the sub-process resumes execution, load eip and esp. After RESTORE_ALL is executed
(Pops, iret), the register is restored, and we know the current ESP
It is different from ESI.
*/
Cmpl % esp, % esi;
Je 1f;/* % esp, % esi is the same, it is the parent process */
Movl % 4, % eax;/* load the parameter to EAX, regardless of whether fn uses the-mregparam attribute
See GCC manual for more information
*/
Pushl % eax/* press the parameter stack */
Call * % 5;/* call fn */
Movl % 3, % 0;
Int $0x80;/* The system calls exit to exit */
1: movl % eax, retval/* pay the pid of the sub-process to retval (the return value of the system call is in % eax )*/
Movl % esi, d0 /*?? */
}
Its pseudo C code is:
Int kernel_thread ()
{
Pid = clone (flags );
If (child)
{
Fn (arg );
Exit (0 );
}
Return pid;
}
From the code above, we can see that the kernel thread has the following properties:
1.
The kernel thread is implemented by calling clone () by the system, and the CLONE_VM flag is used (you can also
Provide other flags, CLONE_PID, CLONE_FS, CLONE_FILES, etc.), so the kernel thread and call
The process (current) has the same process space.
2.
Because the calling process calls kernel_thread () in the kernel, the sub-process is also in
The sub-process then calls fn. When fn exits, the sub-process calls exit () to exit.
Run in kernel mode.
3.
Because the kernel thread runs in the kernel state, the kernel thread can access the data in the kernel and call the kernel function.
Cannot be preemptible during running.
Note how kernel_thread calls the system call. We know that kernel_thread is in the kernel.
So he can directly call the system call, such as sys_open (), but here kernel_thread
When the clone () function is indirectly called through the system call gate (int $80), the following questions are raised:
1. Why?
2. What will happen if we call sys_clone () directly?
Int kernel_thread ()
{
Int pid;
Pid = sys_clone ();
If (! Pid)
{
/* Child */
Exit ();
}
Return pid;
}
In this way, when the sub-process obtains CPU resources (during running), it resumes execution from ret_from_fork. STACK layout is for the sub-process
The problem is that when the sub-process runs to the RESTORE_ALL IRET, think carefully about the STACK layout changes.
The declaration of sys_clone () shows that the stack structure of pt_regs is required to call sys_clone. If we call sys_clone directly
There is no way to do it (if we can, we also need to carefully prepare stack for it, //:-(, it is really sad)
Similarly, other similar system calls must also be implemented through the int $80 system call gate.
For sys_execl, sys_open, sys_close, sys_exit, you can directly call. // xixi. We can
Modify kernel_thread to test whether sys_exit can be called directly. You can also use sys_clone to call it directly.
To verify that our analysis is correct.
If we use the system call gate (int $80) to solve the problem, we use the same method for analysis:
A2)
Ebx <-- (esp after save all, ready for syscils)
Ecx
...
Oldeip <-- (esp before SAVE_ALL which construct stack for syscils)
Oldcs
Eflags
D0 <-(space for local variables)
Retval
Fn <-(arguments for kernel_thread)
Arg
Clone_flags
Eip <-(retore ip for kernel_thread)
..
Because kernel_thread is in the kernel code segment, no stack switching occurs, and all the pressure stacks/rollback stacks are in
In the kernel stack. Please note that there is no (OLDSS, OLDESP) in the stack, so the kernel_thread declares
Two local parameters (retval, d0) have obvious significance for retval, while d0 is probably (dummy local
Variable
0,... n ,:)
B2) before the sub-process runs:
Sub-process TSS, STACK layout
When running to RESTORE_ALL, the various CPU registers are restored. When running to IRET,
Because there is no privilege-level switch in the transfer of the same privilege level, So ESP and SS are not changed.
BTW, according to the above analysis, the process created by kernel_thread cannot be transferred to the user State for running.
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.