Linux0.11 kernel--Process scheduling analysis 1. Initialization

Source: Internet
Author: User

First of all, the MAIN.C function in the main function is the initialization of the process scheduling, sched_init () function, the second function in the SCHED.C implementation:

The scheduler's initialization subroutine.  void Sched_init (void) {int i;  struct DESC_STRUCT *p;//descriptor structure pointer.    if (sizeof sigaction)! =)//sigaction is the structure that holds the state of the signal.  Panic ("Struct sigaction must be bytes");  Sets the task status segment descriptor and local data table descriptor (INCLUDE/ASM/SYSTEM.H,65) for the initial task (task 0).  Set_tss_desc (GDT + first_tss_entry, & (INIT_TASK.TASK.TSS));  Set_ldt_desc (GDT + first_ldt_entry, & (Init_task.task.ldt));  The task array and descriptor descriptor (note i=1 begins, so the descriptor for the initial task is still there).  p = GDT + 2 + first_tss_entry;      for (i = 1; i < nr_tasks; i++) {task[i] = NULL;      P->a = p->b = 0;      p++;      P->a = p->b = 0;    p++; }/* Clear NT, so, we won ' t has troubles with this later on/*/* Clear the bit NT in the flag register, so there will be no trouble later * *//NT flag for Control program recursive call (N ested Task). When the NT is set, then the current interrupt task executes//iret instruction will cause the task to switch.  NT Indicates whether the Back_link field in TSS is valid. __asm__ ("PUSHFL; Andl $0xffffbfff, (%ESP);  POPFL ");//Reset NT flag.  Ltr (0);//The TSS of task 0 is loaded into the task register tr.  Lldt (0);//Loads the local descriptor descriptor into the local Descriptor descriptor register. Attention!! is to Fugazai the selection of the corresponding LDT descriptor in the GDT to LDTR. Only explicitly loaded this time, after the new task//LDT load, isThe CPU is automatically loaded according to the LDT items in the TSS.  The following code is used to initialize the 8253 timer.  Outb_p (0x36, 0x43);/* binary, Mode 3, LSB/MSB, CH 0 */outb_p (LATCH & 0xFF, 0x40);/* LSB *///fixed value low byte.  OUTB (LATCH >> 8, 0x40);/* MSB *///fixed value high byte.  Sets the clock interrupt handler handle (sets the clock interrupt gate).  Set_intr_gate (0x20, &timer_interrupt);  Modify the interrupt Controller Shield code to allow the clock to break.  Outb (Inb_p (0x21) & ~0x01, 0x21);  Sets the system call interrupt gate. Set_system_gate (0x80, &system_call);}

The first initialization of task 0 is Tts,first_tss_entry 4, which indicates that the index in the descriptor is 4. Because the GDT is a desc_struct type of 8 bytes, which is exactly the length of a descriptor, the gdt+4 here can be understood as gdt[4]. Exactly the corresponding is TSS0.

The description of the descriptor is as follows:

0-nul,1-Code snippet is not used cs,2-data segment ds,3-System segment syscall,4-task status Segment tss0,5-Local table ltd0,6-task status segment TSS1, etc.

Sets the task status segment/local table descriptor in the global table. Parameter: n-the address of the descriptor item n in the global table; addr-the base address of the memory where the state segment/local table resides. The type-descriptor byte of a flag. %0-eax (address addr);%1-(Address of descriptor item n);%2-(the address of the descriptor item n is offset 2);/%3-(the address of the descriptor item n is offset by 4);%4-(the address of the descriptor item n is offset 5);//%5-(Descriptor Item n  Address offset 6);%6-(Address offset 7 of descriptor item n), #define _SET_TSSLDT_DESC (N,addr,type) __asm__ ("MOVW $104,%1\n\t" \//place TSS length into Descriptor length field (第0-1 bytes).  The "MOVW%%ax,%2\n\t" \//puts the low word of the base address into the descriptor 第2-3 byte.  The "Rorl $16,%%eax\n\t" \//moves the base address high word into Microsoft Dynamics AX.  The "Movb%%al,%3\n\t" \//moves the low byte of the base address into the 4th byte of the descriptor.  "Movb $" type ",%4\n\t" \//moves the flag type byte into the 5th byte of the descriptor.  The 6th byte of the "Movb $0x00,%5\n\t" \//descriptor is 0.  The "Movb%%ah,%6\n\t" \//moves the high byte of the base address into the descriptor 7th byte.  "Rorl $16,%%eax" \//eax zeroed. :: "A" (addr), "M" (* (n)), "M" (* (n + 2)), "M" (* (n + 4)), "M" (* (n + 5)), "M" (* (n + 6)), "M" (* (n + 7))////Set task status in global table The segment descriptor. N-is the pointer (vector) of the descriptor; addr-is the base address value in the descriptor. The type of the task status segment descriptor is 0x89. #define SET_TSS_DESC (N,ADDR) _set_tssldt_desc (((char *) (n)), addr, "0x89")////set the local table descriptor in the global table. N-is the pointer (vector) of the descriptor; addr-is the base address value in the descriptor. The type of the local table descriptor is 0x82. #define SET_LDT_DESC (N,ADDR) _sEt_tssldt_desc (((char *) (n)), addr, "0x82") 

Since the minimum TSS size is 104 bytes, the first sentence is to assign a length of 104 to the 第0-1 byte of the TTS0 descriptor, the format of the descriptor as described in formatting, and the second sentence to assign the TSS address (n+2) to Ax, which is addr, the first task of the task Union. Because it is a MOVW word, so it is the 第2-3 byte of the descriptor. The 4th byte is then populated, then the type is filled to the 5th byte, and the remaining bytes are finally populated.

The method of initializing the LDT for task 0 is similar, OK, here initialize the TSS and LDT to complete task 0.

Sched_init next is to empty an array of all tasks except task 0 and the corresponding descriptor, which is a good understanding.

Here is the TSS to task register TR that loads task 0, loading the LDT to the local Descriptor descriptor Register LDTR,SCHED.H:

/** looks for a 1th TSS entry in the global table. 0-Not used nul,1-snippet cs,2-data segment ds,3-System segment syscall* 4-task status Segment tss0,5-Local table ltd0,6-task status segment TSS1, etc. See the selector index number of the 1th task State segment (TSS) descriptor in the head.s*///global table. #define FIRST_TSS_ENTRY The selector index number of the 1th Local Descriptor Table (LDT) descriptor in 4//global tables. #define FIRST_LDT_ENTRY (FIRST_TSS_ENTRY+1)//Macro definition, calculates the index number (selector) of the TSS descriptor for the nth task in the global table. #define _TSS (N) (((unsigned long) n) <<4) + (FIRST_TSS_ENTRY<<3))//macro definition, calculates the index number of the LDT descriptor for the nth task in the global table. #define _LDT (N) (((unsigned long) n) <<4) + (FIRST_LDT_ENTRY<<3))//macro definition, load Task Register TR for nth task. #define LTR (N) __asm__ ("Ltr%%ax":: "A" (_TSS (n)))//macro definition, loading the local descriptor of the nth task for the Register LDTR. #define LLDT (N) __asm__ ("Lldt%%ax":: "A" (_ldt (n)))

LDTR Local Descriptor Register: 16 bits, height 13 is the index value that holds the LDT in the GDT.

So First_ldt_entry to the left 3 bits, (((unsigned long) n) <<4) is not very good understanding, because the first to remove the left shift of 3 bits, so the actual value is n<<1, that is, 2n. The final value is equivalent to first_ldt_entry+2n. This makes sense, because each task has two descriptor entries.

Note here: only explicitly loaded this time, after the new task Ldt loading, is the CPU according to the LDT in TSS automatically loaded.

Next is the initialization timer, nothing to say.

The next two sentences are the most critical, and the trigger for process scheduling is initialized below:

  Sets the clock interrupt handler handle (sets the clock interrupt gate).  set_intr_gate (0x20, &timer_interrupt);  Modify the interrupt Controller Shield code to allow the clock to break.  Outb (inb_p (0x21) & ~0x01, 0x21);

The first sentence in the system call mechanism analysis, is to set the interrupt gate, so here is the SYSTEM_CALL.S function Timer_interrupt and the interrupt number 0x20 associated, the following sentence code reference clock Interrupt The clock interrupt is turned on, that is, the 0x20 interrupt, which means that the clock will call the Timer_interrupt function every tick (10ms).

Here, the initialization of the process schedule is over.

Linux0.11 kernel--Process scheduling analysis 1. Initialization

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.