Liu Chang Original works reproduced please indicate the source "Linux kernel Analysis" MOOC course http://mooc.study.163.com/course/USTC-1000029000
Overview
This article mainly analyzes the process of Linux, process scheduling and context switching, it will involve the timing of schedule scheduling and process switching execution process, and through the GDB tracking Linux schedule () function to understand this process in depth.
process scheduling strategy and scheduling timing
Scheduling Policy
The operating system contains many algorithms for process scheduling, and the kernel chooses different scheduling strategies based on the properties of the process. The process can be roughly divided into: IO-intensive and CPU-intensive, in order to make the computer resources have a high utilization, the kernel will be based on the basic properties of the process to choose a different scheduling strategy.
Scheduling type can be divided into time-sharing scheduling and priority scheduling, scheduling is for each process to allocate different times, and priority scheduling from the priority queue to select the highest priority of the process scheduling. It is important to note that during the run process, the priority of the process changes. In general, the longer the process is executed, the lower the priority, and the longer the wait time the priority of the process is gradually increased.
Scheduling Time
In the previous blog post analyzing the Linux system calls, we know that the work_pending will be called once before the system call execution is complete, that is, the process switchover may occur before the system call execution is complete, and it is obvious that the system scheduling is the time of the Linux kernel process scheduling.
The scheduling of a process is implemented by the schedule () function, which is a kernel function, not a user-state function. So the user-state process cannot be called directly, only indirectly, kernel threads are special processes that have no user state in the kernel state. Process scheduling occurs in the following situations:
1. 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;
2. Kernel thread can directly call schedule () for process switching, can also be scheduled during interrupt processing, that is, the kernel thread as a class of special processes can be active scheduling, can also be passive scheduling;
3. The user-state process can not realize the active scheduling, only through the kernel state after a certain point in time to dispatch, that is, in the interrupt processing process scheduling.
Schedule Functions Overview
The schedule function is located in the/kernel/sched/core.c file and its kernel code is described below:
static void __sched __schedule (void) {struct task_struct*prev,*next; unsigned long*switch_count; struct RQ*rq;intCpu;need_resched:preempt_disable (); CPU = smp_processor_id (); RQ = Cpu_rq (CPU); Rcu_note_context_switch (CPU); Prev = rq->curr; Schedule_debug (prev);if(Sched_feat (Hrtick)) hrtick_clear (RQ);/ * * Make sure that signal_pending_state ()->signal_pending () below * can ' t is reordered with __set_current_ State (task_interruptible) * Did by the caller to avoid, the race with Signal_wake_up (). */Smp_mb__before_spinlock (); Raw_spin_lock_irQ (&rq->lock); Switch_count = &prev->nivcsw;if(prev-> State&&! (Preempt_count () & preempt_active)) {if(Unlikely (Signal_pending_state (prev-> State, prev))) {prev-> State= task_running; }Else{Deactivate_task (RQ, Prev, dequeue_sleep); PREV->ON_RQ =0;/ * * If a worker went to sleep, notify and ask Workqueue * whether it wants to wake up a task To maintain * concurrency. */ if(Prev->flags & Pf_wq_worker) {struct TASK_STRUCT*to_wakeup; To_wakeup = wq_worker_sleeping (prev, CPU);if(to_wakeup) try_to_wake_up_local (to_wakeup); }} Switch_count = &prev->nvcsw; }if(task_on_rq_queued (prev) | | Rq->skip_clock_update <0) Update_rq_clock (RQ);Next= Pick_next_task (RQ, prev); Clear_tsk_need_resched (prev); Clear_preempt_need_resched (); Rq->skip_clock_update =0;if(Likely (prev! =Next)) {rq->nr_switches++; Rq->curr =Next; ++*switch_count; Context_switch (RQ, Prev,Next);/ * Unlocks the RQ * */* The context switch has flipped the stack from under US * andRestored theLocalVariables which were saved when* This task called schedule () in the past. Prev = = Current * was still correct, but it can be moved to another CPU/RQ.*/CPU = smp_processor_id (); RQ = Cpu_rq (CPU); }ElseRaw_spin_unlock_irQ (&rq->lock); Post_schedule (RQ); Sched_preempt_enable_no_resched ();if(Need_resched ())Gotoneed_resched;}
The main work of the schedule () function is to select a new process to run through Pick_next_task, and invoke Context_switch for context switching, which calls switch_to for context switching.
The Pick_next_task function is the scheduling strategy in the Linux kernel, which is not in-depth, the purpose of this article is to clarify the Linux process scheduling process.
switching of the process context
The above section says that the process is switching contexts through switch_to, and switch_to is a macro definition, which is described as follows:
#Define SWITCH_TO (prev, Next, last)Do{ /** Context-switching clobbers All registers, so we clobber* them explicitly, via unused output variables.* (EAX and EBP isn't listed because EBP is saved/restored* Explicitly for Wchan access and EAX are the return value of* __SWITCH_TO ())*/unsigned long ebx, ecx, edx, ESI, EDI; ASM volatile ("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"JMP __switch_to\ n"/* regparm call */"1:\ t""Popl%%EBP\ n\ t"/* Restore EBP */"POPFL\ n"/* Restore Flags */ /* OUTPUT Parameters */:[Prev_sp]"=m" (PREV->THREAD.SP), [Prev_ip]"=m" (PREV->THREAD.IP),"=a" (last), /* Clobbered OUTPUT registers: */"=b" (EBX), "=c" (ecx), "=d" (edx),"=s" (ESI), "=d" (EDI) __switch_canary_oparam /* Input Parameters: */:[Next_sp]"M" (NEXT->THREAD.SP), [Next_ip]"M" (Next->thread.ip), /* Regparm parameters for __switch_to (): */ [Prev]"A" (prev), [Next]"D" (next) __switch_canary_iparam :/* Reloaded Segment Registers */"Memory");}while (0)
Prior to the menuos in the Mykernel process context switch is based on this macro-written, it saves the previous process of the ESP, EBP, EIP value, and the next process of ESP, EIP, EBP value into the corresponding registers of the CPU, so that the process of switching. This code is in the form of a macro assembly, the unfamiliar assembly looks very laborious, but to express the purpose is clear, is to save the last process of the ESP, EBP, EIP, and the next scheduled process context into the CPU corresponding registers.
gdb Trace Schedule function Execution Process
The GDB tracking process is similar to those described in previous articles, where breakpoints are set at schedule and the process of kernel process switching executes as follows:
Linux System Execution Overview
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).
Save_all//Save site
Schedule () is called during interrupt processing or before an interrupt is returned, where SWITCH_TO does a critical process context switch
The user-state process y is started after the label 1 (where Y has been switched out through the above steps so it can continue from label 1)
Restore_all//Recovery site
Iret-pop cs:eip/ss:esp/eflags from kernel stack
Continue to run user-state process y
A few special cases:
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, very similar to the most common situation, but the kernel thread is running in the process of interruption without process user state and kernel state conversion;
Kernel thread actively calls schedule (), only the process context of the switch, there is no interrupt context switch, and the most general situation is slightly abbreviated;
The system call that creates the child process starts in the subprocess and returns the user state, such as fork;
A situation in which a new executable program is loaded and returned to the user state, such as EXECVE;
Summary
The scheduling and switching of Linux processes is realized by schedule functions, and the scheduling and switching of processes is a time-out, and it is not possible to schedule and switch processes at any time. In general, in the event of an outage or an exception, Linux can switch processes.
Kernel threads can complete process scheduling by calling schedule, and user processes can enter the kernel state for schedule scheduling only through system calls or exceptions.
Linux kernel Analysis: Experiment eight--linux process scheduling and switching