A brief analysis of the process scheduling of operating system

Source: Internet
Author: User
Tags volatile

Chen Tie + Original works reproduced please specify the source + "Linux kernel analysis" MOOC course http://mooc.study.163.com/course/USTC-1000029000 ". In particular, all the code from Monensin Teacher's Mykernel, perhaps for the purpose of the exercise has been modified, can also be ignored.


The process of learning is in fact a constant imitation, repeating the content of the teacher's presentation, and practicing continuously until it becomes the knowledge that can be expressed independently. I am really stupid, homework reluctantly completed, fortunately, also work hard, spend more time, after all, is the process of their own hard study embodies. So put out to give Fang home a smile, at least is also the harvest of their own learning.


First, the experiment is the experimental building environment, the virtual machine environment is as follows: Linux d0c756f6c18a 3.13.0-30-generic #55-ubuntu SMP Fri Jul 4 21:40:53 UTC x86_64 x86_64 x86_64 Gnu/linux. The experiment starts with simple code and you can see the interrupt schedule demo.

CD linuxkernel/linux-3.9.4

Qemu-kernel Arch/x86/boot/bzimage


Second, copy the teacher's code MYPCH.B,MYMAIN.C,MYINTERRUPT.C to the Mykernel directory. Go back to the kernel directory:

Make all

Qemu-kernel Arch/x86/boot/bzimage

You can see that process scheduling is reflected in the virtual machine. Following:

650) this.width=650; "src=" http://s3.51cto.com/wyfs02/M00/5B/32/wKioL1UCNgqRaXrtAAHEoAz_Ako469.jpg "style=" float: none; "Title=" Qh12. PNG "alt=" Wkiol1ucngqraxrtaaheoaz_ako469.jpg "/>

650) this.width=650; "src=" http://s3.51cto.com/wyfs02/M00/5B/38/wKiom1UCNOrRFLJiAAPPgY7b62w412.jpg "style=" float: none; "Title=" qh30. PNG "alt=" Wkiom1ucnorrfljiaappgy7b62w412.jpg "/>


Third, the following analysis of the code execution process, describe the modern operating system working mechanism.

1. In order to achieve efficient implementation in the Linux core, a large number of inline compilations are used, so let's start with the knowledge of inline assembly. (1) Although modern compiler optimization code, but still compared to handwritten assembly code, (2) some platform-related instructions must be handwritten, there is no equivalent syntax in C language, such as x86 is Port I/O.

    gccProvides an extension syntax to use inline assembly in C code. The simplest format is __asm__("assembly code"); , for example, __asm__("nop"); just executing an empty instruction. To execute multiple assembly instructions, you should \n\t separate the instructions with each one.

Inline assembly to be associated with a variable of C, using the full inline assembly format:

__ASM__ (Assembler template:output operands/* Optional */: Input operands/* Optional */: List of clobbered registers/* optional */);

This format consists of four parts, the first part is the assembly instruction, the second part and the third part is the constraint condition, the second part indicates the output of the assembly instruction to which C operand, the C operand should be an lvalue expression, the third part indicates which C operand the assembly instruction needs to get input from, Part IV is a list of registers that have been modified in the assembly instruction, indicating which register values of the compiler __asm__ will change when the statement is executed. The latter three parts are optional, if you have to fill out, there is no space to write only a : number.

The 2.mypcb.h code is as follows:

/** linux/mykernel/mypcb.h** kernel internal pcb types** copyright  (C)  2013 mengning**/#define  MAX_TASK_NUM 4                //defines the maximum number of processes that the system executes. #define  KERNEL_STACK_SIZE 1024*8     //kernel stack size/* cpu-specific  state of this task */struct thread {                      //Defining Structure Body thread     unsigned long    ip;                 //storing instruction pointers and stack pointers     unsigned long     sp;}; typedef struct pcb{                //struct type Process Control block pcb    int pid;                           //Process id    volatile long state;  /* -1 unrunnable, 0 runnable, >0 stopped */ //Process Status      char stack[kernel_stack_size];        //Process Stack     /* CPU-specific state of this task */     struct thread thread;    unsigned long    task_ entry;    //entrance     struct PCB *next;                //forms a linked list, the next process}tpcb;void my_schedule (void );      //Dispatch function

    3. The following MYMAIN.C main program code

/** linux/mykernel/mymain.c** kernel internal my_start_kernel** copyright  (c)  2013 mengning**/#include  <linux/types.h> #include  <linux/string.h> #include  <linux/ctype.h> #include  <linux/tty.h> #include  <linux/vmalloc.h> #include   "Mypcb.h" tpcb task[max_task_num];      //define the process array Tpcb * my_ current_task = null;  //current process pointer, starting from process No. 0 volatile int my_need_sched = 0; The  //0 process does not need to dispatch void my_process (void); Void __init my_start_kernel (void)      //kernel creation process, starting from process No. 0 to initialize {    int pid = 0;    int  i;    /* initialize process 0*/    task[pid].pid =  pid;            task[pid].state =  0;/* -1 unrunnable, 0 runnable, >0 stopped */    //instruction Pointer to self      task[pid].task_entry = task[pid].thread.ip =  (Unsigned long) my_process;  The     //stack points to the defined kernel stack    task[pid].thread.sp =  (unsigned  long) &task[pid].stack[KERNEL_STACK_SIZE-1];    task[pid].next = & Task[pid];    /*fork more process */    for (i=1;i< max_task_num;i++)     //to start more processes through the fork function, this example 0,1,2,3    {         //We are a simple demo, here directly copy the status of Process No. 0 as a new process          memcpy (&task[i],&task[0],sizeof (TPCB));         task[i]. pid = i;        task[i].state = -1;         task[i].thread.sp =  (Unsigned long) &task[i].stack[KERNEL_STACK_SIZE-1];         task[i].next = task[i-1].next;    //processes form a linked list          task[i-1].next = &task[i];    }     /* start process 0 by task[0] */ //START Process # No. 0      pid = 0;    my_current_task = &task[pid];     /*         Inline assembly,%0,%1 represents the variable "C" for the input and output section for ECX, "D" for edx, "=m "Indicates that the memory         %%reg represents the register. The \n\t means the end.          The following assembly code is not difficult to understand, is for efficiency. Build up the operating environment of the CPU and start the process of No. No. 0.     */    asm volatile (          "Movl %1,%%esp\n\t" &NBSP;/*&NBSP;SET&NBSP;TASK[PID].THREAD.SP&NBSP;TO&Nbsp;esp */         "pushl %1\n\t" &NBSP;/*&NBSP;PUSH&NBSP;EBP  */         "pushl %0\n\t"  /* push task[pid]. thread.ip */         "ret\n\t"  /* pop task[pid]. thread.ip to eip */         "popl %%ebp\n\t"          :        :  "C"   ( TASK[PID].THREAD.IP), "D"   (TASK[PID].THREAD.SP)  /* input c or d mean % ecx/%edx*/    );     }    /* The following is the code that our simple process executes, Used to let humans know which process the CPU is performing. In fact, many operating system processes      just perform in the background, do not need human interaction, but we do not ignore them.     */    void my_process (void)     {         int i&nbSp;= 0;        while (1)          {            i++;         if (i%10000000 == 0)     //loop 10 million times, output a process ID, active scheduling, to avoid the message mechanism.         {           &NBSP;&NBSP;PRINTK (kern_notice  "this is process %d -\n", my_current_task->pid);             if (my_need_sched == 1)              {                 my_need_sched = 0;                 my_schedule ();         &nBSP;&NBSP;&NBSP;&NBSP;}&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK (KERN_ notice  "this is process %d +\n", My_current_task->pid);         }    }}

        4. The following is the code for MYINTERRUPT.C and a brief description:

/** linux/mykernel/myinterrupt.c** kernel internal my_timer_handler** copyright  (C)  2013 mengning**/#include  <linux/types.h> #include  <linux/string.h> #include  <linux/ctype.h> #include  <linux/tty.h> #include  <linux/vmalloc.h> #include   "Mypcb.h" Extern tpcb task[max_task_num];extern tpcb * my_current_task;extern  volatile int my_need_sched;volatile int time_count = 0;     //time count has been implemented actively, our simple code does not accept input/** called by timer interrupt.* it runs in  the name of current running process,* so it use kernel  stack of current running process*/void my_timer_handler (void) {      #if  1    //Count 1000 times and do not switch the process to output a line of reminders     if (time_count% 1000 == 0 && my_need_sched != 1) &NBSP;&NBSP;&NBSP;&NBSP;{&NBSP;&NBSP;&NBSP;&NBSP;PRINTK (KERN_NOTICE  ">>>my_timer_handler here<<<\n");    my_need_sched = 1;     }    time_count ++ ;     #endif      return;} Void my_schedule (void) {    tpcb * next;    tpcb *  prev;    if (my_current_task == null    | |  my_current_task->next == null)     {         return;                 //error Handling &NBSP;&NBSP;&NBSP;&NBSP;}&NBSP;&NBSP;&NBSP;&NBSP;PRINTK (kern_notice  ">>>my_schedule <<<\n ");     /* schedule */    next = my_ CurRent_task->next;    prev = my_current_task;    if (next- >state == 0)/* -1 unrunnable, 0 runnable, >0 stopped */     {    /* switch to next process */  The key code for the    //process switch is essentially the same as the analysis function call, saving the current context     asm volatile (      "pushl %%ebp\n\t"  /* save ebp */     "Movl %%esp, %0\n\t " /* save esp */    " movl %2,%%esp\n\t " /*  restore esp */     "movl $1f,%1\n\t"  /* save eip */          "pushl %3\n\t"      "ret\n\t"  /*  restore eip */     "1:\t"  /* next process start  here */    " Popl %%ebp\n\t "    : " =m "  (PREV-&GT;THREAD.SP)," =m "  (prev-> THREAD.IP)     :  "M"   (NEXT-&GT;THREAD.SP), "M"   (NEXT-&GT;THREAD.IP)      ); &NBSP;&NBSP;&NBSP;&NBSP;MY_CURRENT_TASK&NBSP;=&NBSP;NEXT;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK ( kern_notice  ">>>switch %d to %d<<<\n", Prev->pid,next->pid);     }    else    {    next->state &NBSP;=&NBSP;0;&NBSP;&NBSP;&NBSP;&NBSP;MY_CURRENT_TASK&NBSP;=&NBSP;NEXT;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK (KERN_ notice  ">>>switch %d to %d<<<\n", Prev->pid,next->pid);     /* switch to new process */    //set up a new operating environment, Start the new process by starting from the newly-executed line of code.     asm volatile (     "pushl %%ebp\n\t"  /* save  ebp */     "movl %%esp,%0\n\t"  /* save esp */     "MOVL  %2,%%esp\n\t " /* restore esp */    " movl %2,%%ebp\n\t "  /* restore ebp */     "movl $1f,%1\n\t"  /* save  eip */         "pushl %3\n\t"      "ret\n\t " /* restore eip */    : " =m "  (PREV-&GT;THREAD.SP)," =m "   (PREV-&GT;THREAD.IP)     :  "M"   (NEXT-&GT;THREAD.SP), "M"   (next-> THREAD.IP)     );     }    return;}

Four, the experimental summary, the teacher simplified code is not difficult to understand, but to write their own do not have this ability, so directly copied down their own understanding, the implementation of the process did not appear error. While simplifying the code, it is helpful to understand how the operating system works. The first is the kernel bootstrap, after all, all the programs are just memory code, the kernel is just that the designated privileges, NO. 0 process, start running, and build their own environment. Second, after all, the operating system is for the actual program services, the next is responsible for creating other process execution environment, resource allocation, the use of linked list mechanism to switch to the new process, and execution. Finally, the kernel is responsible for managing the state of the process, using the interrupt mechanism to implement process switching and control program execution. In summary, the operating system does the processing of the interrupt context and the process switching context.

This article is from the "Studypark" blog, make sure to keep this source http://swordautumn.blog.51cto.com/1485402/1619999

A brief analysis of the process scheduling of operating system

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.