Shinakawa + Original works reproduced please specify the source + "Linux kernel analysis" MOOC course http://mooc.study.163.com/course/USTC-1000029000
Linux supports both common ticks and real-time processes, which are priority-based. Scheduling in Linux is a mixture of various scheduling strategies and scheduling algorithms, because different types of processes have different scheduling requirements, so the timing of scheduling is also different. These algorithms allow the system to run more efficiently, maximizing CPU utilization. The so-called strategy is a set of rules that determines when and how to choose a new process to run. The principle of operating system describes a large number of process scheduling algorithms, these algorithms from the perspective of implementation is only to choose a new process from the run queue, the process of selecting the use of different strategies. It is more important to understand the working mechanism of the operating system than the process scheduling timing and process switching mechanism.
The scheduling of processes in Linux relies on the schedule () function, which we follow through GDB.
analyze a schedule () function using GDB trace
Set breakpoints
Schedule
Schedule called the __schedule
Pick_next_task is called in __schedule to select a new process to run, and then invoke Context_switch for context switching
Context_switch
Timing of process scheduling
Interrupt processing (including clock interrupts, I/O interrupts, system calls, and exceptions), call schedule () directly, or call schedule () based on the need_resched tag when returning to the user state;
Kernel threads can directly call schedule () for process switching, or in the process of interrupt processing, which means that kernel threads as a special kind of process can be active scheduling, but also can be passively dispatched;
The user-state process cannot implement the active scheduling, but can only be dispatched by a point in time after the kernel state, that is, scheduling during interrupt processing.
Switch_to
#defineSwitch_to (prev, next, last) \ + Do { - /** context-switching clobbers all registers, so we clobber * them expl icitly, via unused output variables. * (EAX and EBP are not listed because EBP are saved/restored PNS * explicitly for Wchan access and EAX are the R Eturn value of $ * __switch_to ())*/ +UnsignedLongebx, ecx, edx, ESI, EDI; A theAsmvolatile("pushfl\n\t" /*Save Flags*/ + "PUSHL%%ebp\n\t" /*Save EBP*/ - "MOVL%%esp,%[prev_sp]\n\t" /*Save ESP*/ $ "MOVL%[next_sp],%%esp\n\t" /*Restore ESP*/ $ "MOVL $1f,%[prev_ip]\n\t" /*Save EIP*/ - "PUSHL%[next_ip]\n\t" /*Restore EIP*/ -__switch_canary the "jmp __switch_to\n" /*Regparm Call*/ - "1:\t" Wuyi "popl%%ebp\n\t" /*Restore EBP*/ the "popfl\n" /*Restore Flags*/ - Wu /*Output Parameters*/ -: [PREV_SP]"=m"(prev->thread.sp), About[PREV_IP]"=m"(prev->Thread.ip), $ "=a"(last), - - /*clobbered output registers:*/ - "=b"(EBX),"=c"(ECX),"=d"(edx), A "=s"(ESI),"=d"(EDI) + the__switch_canary_oparam - $ /*Input Parameters:*/ the: [NEXT_SP]"m"(next->thread.sp), the[NEXT_IP]"m"(next->Thread.ip), the the /*regparm parameters for __switch_to ():*/ -[Prev]"a"(prev), in[Next]"D"(Next) the the__switch_canary_iparam About the:/*Reloaded Segment Registers*/ the "Memory"); the} while(0)
Switch_to (prev, Next, prev) was called in Context_switch, and the context save and switch tasks were completed, and Prev and next pointed to the current process and the next process to be switched.
42 43 The current process of the flags and EBP stack; 44 The current ESP is saved to memory, and 45 is stored in the next process by the ESP, which has been switched to the stack of the next process; 46 47 Saves the current process's $1f label to the current IP and the next process's IP stack; 48 49 after executing the function iret the next process IP out of the stack, this switch to the next process; Finally, the EBP and flags out of the stack, formally executing the next process
Switch_to the corresponding stack
Asmvolatile("pushfl\n\t" /*Save Flags*/ + "PUSHL%%ebp\n\t" /*Save EBP*/ - "MOVL%%esp,%[prev_sp]\n\t" /*Save ESP*/ $ "MOVL%[next_sp],%%esp\n\t" /*Restore ESP*/ $ "MOVL $1f,%[prev_ip]\n\t" /*Save EIP*/ - "PUSHL%[next_ip]\n\t" /*Restore EIP*/\
"Movl%[next_sp],%%esp\n\t"/* Restore ESP
"Movl $1f,%[prev_ip]\n\t"/* Save EIP * /These two sentences save and switch the SP of the stack
Then the next process IP stack
-__switch_canary the "jmp __switch_to\n" /*Regparm Call*/ - "1:\t" Wuyi "popl%%ebp\n\t" /*Restore EBP*/ the "popfl\n" /*Restore Flags*/\
Next_stack becomes prev_stack,next_ip out of the stack, switches to the next process, and then pops EBP POPFL starts executing the next process code
$1F is the same address, but it has a different context.
Summarize
First, when the X user state process through the process scheduling policy switch to the user state process Y,
The most common scenario: The running user-state process x switches to the process of running user-state process y
1. Running user-state process X
2. Interrupt--save Cs:eip/esp/eflags (current) to kernel Stack,then load Cs:eip (entry of a specific ISR) and Ss:esp (point to Kern El Stack).
3.save_all//Save site
4. Schedule () is invoked during interrupt processing or before an interrupt is returned, where SWITCH_TO does a critical process context switch
5. After the label 1 begins to run the user-state process y (here Y has been switched out through the above steps so you can continue from the label 1)
6.restore_all//Recovery site
7.iret-pop cs:eip/ss: esp/eflags from kernel stack
8. Continue to run the user-state process y
Several special cases
1. By interrupting the timing of the processing process, the user-state process and kernel threads switch between each other and the kernel threads switch to each other, and the most common situation is very similar, but the kernel thread is running in the process of interruption without process user state and kernel state conversion;
2. Kernel thread actively calls schedule (), only the process context switch, there is no interrupt context switch, and the most general situation is slightly abbreviated;
3. Create a child process of the system call in the child process execution starting point and return user state, such as fork;
4. After loading a new executable program, return to the condition of the user state, such as EXECVE;
Second, the relevant process switch
1. In order to control the execution of the process, the kernel must have the ability to suspend a process that is executing on the CPU and resume execution of a previously suspended process, called process switching, task switching, context switching;
2. Suspend the process that is executing on the CPU, which is different from the save scene at the time of interruption, before and after the interruption is in the same process context, only by the user state to the kernel state execution;
3. The process context contains all the information required for process execution
(1) User address space: Including program code, data, user stack, etc.
(2) Control information: Process descriptor, kernel stack, etc.
(3) Hardware context (note that interrupts are also saved by the hardware context, only the method of saving is different)
The 4.schedule () function selects a new process to run and invokes Context_switch for context switching, which calls switch_to for critical context switching
(1) Next = Pick_next_task (RQ, prev);//process scheduling algorithms encapsulate this function inside
(2) Context_switch (RQ, Prev, next);//process Context switch
(3) Switch_to takes advantage of Prev and next two parameters: Prev points to the current process, next points to the scheduled process
The kernel is a collection of various interrupt processing processes and kernel threads, and more than 3g is shared by all processes
The process of understanding process scheduling and process switching during the time-tracking analysis process