This article is part II of the "reading thin"linux core design and implementation "series, which focuses on the following issues: Process management tasks, process management and other module dependencies, process descriptors and task queues, process creation, thread implementation, process termination, process scheduling.
0x00 Process-managed tasks
Process can create a new process (by copying an existing process)
Determine which process can own the CPU
Accepting interrupts and directing interrupts to the appropriate kernel subsystem
Managing Clock Hardware
Release its resources when a process ends
Dynamic load Execution Module
0X01 process Management dependencies to other modules I-process module internal and external interface
II process modules and other modules of the dependency relationship
Memory Management module: When a process is dispatched, a memory map is established for it
IPC module: Bottom-half processing uses the semaphore queue
File System module: Provides access to the actual device for process scheduling while loading the module
All other modules depend on the process scheduling module because they require the CPU to suspend the user process and switch to the system state for processing when hardware access is required
0X02 process descriptor and Task queue I process descriptor
II Assigning process descriptors
- Linux
task_struct
can achieve object reuse and cache coloring by slab allocation, and does not require frequent calls to memory management functions, equivalent to a high-level cache
Iii. Storage of process descriptors
Through the current macro (architecture-related),current_thread_info()->task;
0X03 process Creation I process create process description
In Linux, process creation is accomplished by copying existing processes
When the kernel starts, it start_kernel()
initializes the system data structures and generates a background process that survives the system: Init
These sub-processes fork()
generate their child processes through system calls
The termination of a process is implemented through a system call _exit()
II Process Creation function
III Write-time copy (Copy-on-write)
Causes the copy of the page on the address space to be deferred until the actual write occurs
Implementation of the 0X04 thread
Linux does not have a real thread, threads are implemented as processes (just a mechanism for direct sharing of resources between processes)
Some parameter flags are passed through clone to achieve:
clone0);
These flags are defined in <linux/sched.h>
- Kernel threads: Running standard processes independently on the kernel
Terminating delete process descriptor for the 0x05 process
The parent process will not be able to delete the child process's descriptor until it learns that the process has terminated
Parent Process WAIT () (implemented through system call wait4()
), suspends the parent process until one of the child processes exits
After that, the real release descriptor ( release_task()
):
- Call to
_unhash_process()
remove the process from Pidhash
_exit_signal()
Release the remaining resources used by the current zombie process
- Call
put_task_struct
Release descriptor (kernel stack, page thread_info, slab cache)
What happens if the parent process terminates abnormally?
If the parent process is rolled out before the child process, these orphaned processes are in a zombie state, and the solution is to find a father in the current process for the child thread, and if not, the Init process is the father, the process:
do_exit() -> exit_notify() -> forget_original_parent() -> find_new_reaper()
began to seek the father.
0X06 process scheduling I multi-tasking system classification
Preemptive: The scheduler determines the running and suspending of a process, the suspended action is called preemption (Linux is a preemptive kernel), and the elapsed time of the process before being preempted is pre-set, called the time slice
Non-preemptive: unless the process stops itself, it will run until it actively suspends its actions called concessions (yielding)
II scheduling policy I/O consumption and CPU-consuming processes
UNIX family tends to I/O consumption type
Process priority (Linux takes 2 different priority ranges)
Nice value: From -20~+19, the default is 0,nice, the higher the priority level
Real-time priority: the higher the real-time priority from 0~99, the higher its value can be configured
Time slices
How much time slice allocation? : The time slice is too long makes the system interactivity is not good, the time slice too short can cause most CPU time to waste in the process switch.
Linux uses a variable length of time slice
III Linux scheduling algorithm O (1) Scheduling Priority series Group
O (1) A core data structure in the scheduling algorithm is a prio_array
struct, in which there is a queue that represents the dynamic priority of a process, each of which is a list of prioritized processes in which the processes in each list have the same priority
struct prio_array{ unsignedint nr_active; unsignedlong bitmap[BITMAP_SIZE]; structqueue[MAX_PRIO];}
In addition, the struct also contains a priority bitmap bitmap, which uses 1 bits to represent 1 priorities, starting with all positions at 0, and once the process is in a running state, the priority of the process corresponds to the corresponding bit in the bitmap is set to 1.
Therefore, finding the highest priority in the O (1) schedule translates to the first bit of 1 in the Find priority bitmap
Once the highest priority has been determined, selecting the next process takes a process in the linked list of the queue.
Active processes and expired processes
In O (1) Scheduling, there are two types of processes that can be run: one for the active process , one for the time slice, and one for the overdue process , that is, the process that the time slice is exhausted, but the process is not finished and they have no chance of being executed.
The two elements of arrays in the run queue structure (RUNQUEUE) represent the two sets respectively, active
and expire
Two pointers point to the 2 sets respectively
Calculation of time slices
active
In the process once the time slice is used, it will be put expire
in, and set a new time slice; when active
empty, it indicates that all process time slices have been exhausted, at this time, will active
and expire
swapped, restart the next round of the decrement process of the time slice.
O (1) Two cores in an algorithm
CFS Dispatch (Fair Dispatch)
The O (1) algorithm is scheduled according to the priority of the process, and the CFS is scheduled based on the process's virtual process run time.
How do I select a process?
CFS presents the concept of Virtual runtime (Vruntime), Vruntime records the total amount of time an executable process can execute up to the current time, and the greater the vruntime, the less likely it is to be dispatched, so each time you select Vruntime Smaller processes are scheduled (using red-black trees in Linux to find the smallest vruntime process)
Running time of the scheduling process
Now that you know how the process is scheduled, how much time does it run when the process is running?
The runtime of the CFS is determined by the priority weighting of all currently scheduled processes
Example: 3 process priority is 5,15,20, their time slice size allocation is: 5/40, 15/40, 20/40
IV preemption and Context switching
Context switching means switching from one executable process to another executable (defined in Sched.h context_switch ())
Invoke switch_mm()
: Switch virtual process from one process to new process
Invoke switch_to()
: Save and restore stack information, register information
need_resched
Flags: Each process contains this flag, in order for the kernel to know when to invoke it. When a schedule()
process should be preempted, the flag is set, and the flag is set when a high-priority process enters the executable state.
The occurrence of user preemption
User preemption occurs when the kernel returns to user space and is need_resched
set to cause a schedule()
call
The occurrence of kernel preemption
When returning kernel space from the interrupt program
Once the kernel code is once again preemptive
If the task in the kernel displays the callschedule()
If a task in the kernel is blocked (also called schedule()
)
This article's copyright belongs to the author Luo voyage All, uses Attribution-noncommercial 3.0 License. Any person may reproduce, share, but not be used without permission for commercial purposes; reprint please specify the source. Thanks for cooperating!
Design and implementation of read-thin "linux Cores" (2)-Process management and scheduling