Process switching through GDB tracking process scheduling analysis process

Source: Internet
Author: User
Tags exit in prev

Kuregaku Shandong Normal University

"Linux kernel Analysis" MOOC course http://mooc.study.163.com/course/USTC-1000029000

The purpose of this experiment is to trace the process of a simple command-line command implementation process through GDB, and analyze the process of process switching in general user process, and further analyze the principle of process scheduling.

First, the experimental process

1. Open the experimental environment and set the Context_switch and Pick_next_switch two breakpoints.

2, to the second breakpoint list (analysis in the third part)

3, to the first breakpoint, where the process of switching

4, find the main body of the schedule () function, you can press step into enter, the process is no longer one by one repeat.

Second, schedule () part of the key Code analysis

1, schedule () code interception

Prev->sched_class->put_prev_task (RQ, prev);        Next = Pick_next_task (RQ, prev);        if (likely (prev! = next)) {                Sched_info_switch (prev, next);                rq->nr_switches++;                Rq->curr = Next;                ++*switch_count;                Context_switch (RQ, Prev, next); /* Unlocks the RQ */*                 * The context switch might has flipped the stack from under                 * us, hence refresh the L ocal variables.                 *                /CPU = SMP_PROCESSOR_ID ();                RQ = CPU_RQ (CPU);        } else                SPIN_UNLOCK_IRQ (&rq->lock);

It is not difficult to find that the first sentence of the prev was previously assigned to Rq->curr, so is the current running queue running process. The literal view is to put the current process back into the queue. The second sentence is to remove the next running process from the queue, called next.

Here is the context switch work for the process. First determine if Prev and next are the same process, and if so, you do not have to switch. Otherwise, set Rq->curr to Next, and then call Context_switch for the actual context switch.

Understanding process scheduling, the core is put_prev_task and pick_next_task, while understanding the process of switching, the core is context_switch. The following two clues, respectively, describes the process of switching and scheduling process.

2, see pick_next_task function body below.

static inline struct task_struct *  pick_next_task (struct RQ *rq)  {      const struct Sched_class *class;      struct task_struct *p;      /* * Optimization:we know if all tasks is in      * The Fair class we can call that function directly:      */
   if (likely (rq->nr_running = = rq->cfs.nr_running)) {          p = fair_sched_class.pick_next_task (RQ);          if (likely (p))              return p;      }        class = Sched_class_highest;      for (;;) {/* for each dispatch class */          * Call the function in the dispatch class to find the next task *          /p = class->pick_next_task (RQ);          if (p)              return p;          /* * Never is NULL as the Idle class always          * Returns a non-null p: */          class = class->next;/* Access the next dispatch class */      }  }  

Call Pick_next_task () and select the next process to run from the run queue.

3, Next analysis Context_switch () implementation of the function:

static inline void Context_switch (struct rq *rq, struct task_struct *prev, struct task_struct *next) {        struct mm_struct *mm, *oldmm;      Prepare_task_switch (RQ, Prev, next);      Trace_sched_switch (RQ, Prev, next);      MM = next->mm;      OLDMM = prev->active_mm; /* for Paravirt, which is coupled with a exit in switch_to to * combine the page table reload and the Switch B      Ackend into * one hypercall.        */Arch_start_context_switch (prev); if (unlikely (!mm)) {/* If the mm of the process being switched in is empty */next->active_mm = OLDMM;/* will share the active_mm of the switch out process */ATOMIC_ Inc (&oldmm->mm_count);      /* There is a process share, all reference counts plus one *///* Set the per CPU variable cpu_tlbstate state to Lazy */enter_lazy_tlb (OLDMM, next);        } else/* if mm is not empty, then do mm toggle */switch_mm (OLDMM, MM, next);           if (unlikely (!prev->mm)) {/* If the switch-out mm is empty, you can see from above that the active_mm of this process is to share the active_mm of the previously switched-out process, all of which need to be empty here */ PREV->ACTIVE_MM = NULL; rq->prev_mm = OLDMM; /* Update the previous MM structure of RQ */}/* * Since the Runqueue lock would be released by the next * task (which are an INV Alid locking op But in the case * of the scheduler it's an obvious special-case), so we * does an early LOCKDEP re  Lease here: */#ifndef __ARCH_WANT_UNLOCKED_CTXSW spin_release (&rq->lock.dep_map, 1, _THIS_IP_);        #endif/* Toggle Register Status and Stacks here */switch_to (prev, Next, prev);      Barrier (); /* * THIS_RQ must be evaluated again because Prev could have moved * CPUs since it called schedule (), thus the ' RQ      ' On its stack * frame'll be invalid.  */Finish_task_switch (THIS_RQ (), prev);   }

The core function of schedule is to switch to new memory pages, register states and stacks, and to clean up after switching. where call Switch_to () toggles the register state and stack of the process, we focus on this part.

4, switch_to for kernel stack and CPU environment switch operation:

/* * Saving eflags is important.  It switches not only IOPL between tasks, * It also protects other tasks from NT leaking through sysenter etc.                              */#define SWITCH_TO (prev, next, last) \ Do {\/* \ * Context-switching Clobbers all registers, so we clobber \ * them explicitly, via unused out        Put variables. \ * (EAX and EBP are not listed because EBP are saved/restored \ * Explicitly for Wchan access and EAX are the Retu RN 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 */\" mov L%[next_sp],%%esp\n\t "/* restore ESP */\" MOVL $1f,%[prev_ip]\n\t "/* Save EIP */\/* will next_ip into the stack, the following in jmp jump, so return to the label 1 o'clock switch over the * *" PU SHL%[next_ip]\n\t "/* restore EIP */\ __switch_canary \" JMP __switch_t o\n "/* regparm call */\" 1:\t "\/* Switch to the first instruction of the new process */" pop                                      L%%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" (E                 CX), "=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)

It can be seen that the steps are split into two steps:

① switching the kernel stack

This macro first saves the ebx,ecx,edx,esi,edi,flags on the current kernel stack and then makes a critical stack switch:

PUSHL%ebpmovl%esp,%[prev_sp]mvol%[prev_sp],%esp

First, stack frame EBP is pressed, and then the last process is removed from the PREV->THREAD.SP in the top of the stack at the last switch, and placed in the ESP. After this sentence, the kernel-state stack has switched to the kernel stack of the next process. This function is called by the Current_thread_info feature described earlier, which will get the thread_info of next.

② Switching Kernel control flow

Then start switching the control process:

MOVL $1f,%[PREV_IP]PUSHL%[next_ip]jmp __switch_to1:popl%EBP

First put the label 1, that is, the address of the last sentence of the paragraph into Prev->thread.ip. The next time the prev is run, it will start with the pop%ebp. Then, next->thread.ip the stack and jump to __switch_to execution.

When __switch_to returns, it pops an entry from the stack as the return address, because the call to __switch_to is not done by calling instruction, but by manually pressing the stack and jumping, so it will not return to the "Here" label 1, but return to the Next->thread.ip place. If the next process is not newly created, then the original is also through the switch_to switch, then the breakpoint must be "there" of the label 1, and at this time next on the kernel stack is saved with the EBP and flags, and EBX and so on.

Therefore, through this function call, the kernel control process has been successfully transferred to next, at next the last switch of the label 1, the last saved EBP and flags and other content to restore, this completes the entire switching process.

Iii. Summary and Reflection

A general process switching process in which the key operations that must be completed are: Switching the address space, switching the kernel stack, switching the kernel control flow, plus some necessary registers to save and restore. Here, except for the switching of the address space, the word "kernel" should be emphasized in other operations. This is because these actions are not intended for user code, and are not executed immediately after the switch is complete and in the user space of next. The Save and restore of the user context occurs when the kernel state and the user state switch between the interrupt and the exception mechanism. Schedule () is the kernel and other parts of the portal used to invoke the process scheduler, choosing which process can run and when it will be put into operation.

Process switching through GDB tracking process scheduling analysis process

Contact Us

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.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.