Operating system Ucore LAB4 Experimental report

Source: Internet
Author: User

operating System LAB4 experimental report

This experiment will touch on the management of kernel threads. Kernel threads are a special process, with two differences between kernel threads and user processes: Kernel threads run only in the kernel state and user processes run alternately in the user and kernel states, and all kernel threads use the common ucore kernel memory space directly. There is no need to maintain separate memory space for each kernel thread and user processes need to maintain their own user memory space.

After the completion of this experiment, in order to deepen understanding, I here simply to re-read all the previous code and comb it again, a simple summary.

This is primarily kern_init the beginning of the physical memory management initialization of the function, as follows:

In the order of the functions I made a brief summary as follows:

    • 1, pmm_init ()
      • (1) initializes the physical memory manager. The
      • (2) initializes the free page, primarily the page data structure that initializes the physical page, and the table and page tables that are created.
      • (3) initializes the BOOT_CR3 to point to the first Page directory table address of the Ucore kernel virtual space, which is the starting physical address of the first-level page table.
      • (4) Initializes the first page of table Boot_pgdir.
      • (5) initializes the GDT, which is the Global descriptor table.
    • 2, pic_init ()
      • Initialize 8259A interrupt Controller
    • 3, idt_init ()
      • initializes the IDT, which is the interrupt descriptor,
    • 4, vmm_init ()
      • The main experiment is a The Do_pgfault () function reaches the page fault exception handling function, as well as virtual memory related MM,VMA structure data creation/destruction/find/insert functions such as
    • 5, proc_init ()
      ul>
    • This function initiates the process of creating a kernel thread, completing the creation or copying of idleproc kernel threads and initproc kernel threads, which is the focus of this experimental analysis and will be analyzed in detail later.
  • 6, ide_init ()
    • Complete initialization of the hard disk (Swap hard disk) used for page swap out
  • 7, swap_init ()
    • swap_init () function first establishes the main function module that completes the page replacement process, which is Swap_manager, which contains the implementation of the page replacement algorithm
    • /ul>
Exercise 0 Filling out an existing experiment

We also use meld software to compare. Roughly as follows:

After comparison and modification, I will list the files I need to modify as follows:

default_pmm.cpmm.cswap_fifo.cvmm.ctrap.c
Exercise 1 assigning and initializing a Process control block

The operating system is a process-centric design, so its first task is to create a file for the process, which is used to represent, identify, or describe the process, the process control block. What needs to be done here is the initialization of a process control block.

And here we are allocating a kernel thread PCB , which is usually just a small piece of code or function in the kernel, with no user space. Because the entire core memory space has been managed since the operating system was started, the setting of the page table establishes the core virtual space (that is, the boot_cr3 space described by the Level Two page table). So all the threads in the kernel do not need to build their own page tables, just share the core virtual space to access the entire physical memory.

The kern/process/proc.h PCB structure of the process control block is defined first in the proc_struct following:

structproc_struct {enumProc_state State;//Process State    intpid//Process ID    intRuns//The running times of Procesuintptr_t Kstack;//Process kernel stack    volatile BOOLneed_resched;//bool Value:need to is rescheduled to release CPU?    structProc_struct *parent;//The parent process    structMm_struct *mm;//Process ' s memory management field    structContext context;//Switch here to run process    structTrapframe *TF;//Trap frame for current interruptuintptr_t CR3;//CR3 register:the Base addr of Page Directroy Table (PDT)uint32_t flags;//Process flag    CharName[proc_name_len +1];//Process namelist_entry_t List_link;//Process link listlist_entry_t Hash_link;//Process Hash list};

Here is a brief description of each parameter:

    • State: The status in which the process is located.

      Proc_uninit//Not in initial state
      Proc_sleeping//Sleep (blocking) status
      Proc_runnable//Run and ready state
      Proc_zombie//Zombie State

    • PID: Process ID number.

    • Kstack: The location of the kernel buyers assigned to the process/thread is recorded.
    • Need_resched: Whether scheduling is required
    • Parent: The parental process of the user process.
    • MM: The structure of the process virtual memory described in experiment three
    • Contextual: The context of the process used for process switching.
    • TF: A pointer to a broken frame that always points to a location on the kernel stack. The interrupt frame records the status of the process before it is interrupted.
    • CR3: Records the address of the page table currently in use

And here we need to complete a alloc_proc function to be responsible for assigning a new struct proc_struct structure, according to the hint we have to initialize some variables, the specific code is as follows:

static struct proc_struct*Alloc_proc (void) {struct PROC_STRUCT*Proc=Kmalloc (sizeof (struct proc_struct));if(proc!= NULL) {proc -State=Proc_uninit;//Set process to uninitialized stateProc -Pid= -1;//Uninitialized process ID is-1Proc -Runs= 0;//Initialize time slicesProc -Kstack= 0;//Memory stack addressProc -Need_resched= 0;//Whether scheduling is required to be set to NoProc -Parent = NULL;//parent node is set to nullProc -Mm= NULL;//virtual memory set to nullMemset&(proc -Context),0, sizeof (struct context));//initialization of the contextProc -Tf= NULL;//Interrupt frame pointer is set to NULLProc -Cr3=BOOT_CR3;//Page directory set as base address for the Kernel page catalog tableProc -flog== 0;//Flag bitmemset (proc -Name0, Proc_name_len);//Process name}returnproc;}

The first one sets the status of the process to "initial", which indicates that the process has been "born";
The second statement sets the process pid to 1, which means that the "ID number" of the process has not been done well;
The third statement indicates that because the kernel thread is running in the kernel, it takes a ucore page table that has been created for the kernel, which is set to the ucore starting address of the kernel page table boot_cr3 .

Exercise 2 Assigning resources to newly created kernel threads

alloc_procIn essence, only a small chunk of memory is found to record the necessary information for the process, and there is no actual allocation of these resources, and Exercise 2 completes the do_fork task of actually completing the allocation of resources, and of course, do_fork just creating a copy of the current kernel thread, with the same execution context, code, and data. But the storage location is different.
According to the prompt and read the source, it is completed the main work is as follows:

    • 1. Assign and initialize the Process control block ( alloc_proc function);
    • 2. Allocate and initialize kernel stacks ( setup_stack functions);
    • 3. clone_flag copy or share the process memory management structure (function) according to the flag copy_mm ;
    • 4. Set the interrupt frame and execution context required for normal operation and scheduling of the process in the kernel (also including user Configuration in the future)
      ( copy_thread function);
    • 5. Put the set of process control blocks into the list of hash_list proc_list two global process chains;
    • 6. Since then, the process is ready to execute, setting the process state to "ready";
    • 7. Set the return code to the number of the child process id .

Complete the code as follows: Detailed comments are shown in the code

intDo_fork (uint32_t clone_flags, uintptr_tStack,structTrapframe *TF) {intret =-e_no_free_proc;structProc_struct *proc;if(Nr_process >= max_process) {GotoFork_out; } ret =-e_no_mem;//1: Call the Alloc_proc () function to request a block of memory, if it fails, return the processing directly    if((proc = Alloc_proc ()) = = NULL) {GotoFork_out; }//2. Setting the parent node of a child process to the current processProc->parent = current;//3. Call the Setup_stack () function to assign a kernel stack to the process    if(Setup_kstack (proc)! =0) {GotoBad_fork_cleanup_proc; }//4. Calling the Copy_mm () function to copy the memory information of the parent process to the child process    if(Copy_mm (Clone_flags, proc)! =0) {GotoBad_fork_cleanup_kstack; }//5. Calling the Copy_thread () function to copy the interrupt frame and context information for the parent processCopy_thread (proc,Stack, TF);//6. Adding a new process to the hash list of a process    BOOLIntr_flag;    Local_intr_save (Intr_flag);        {proc->pid = Get_pid (); Hash_proc (proc);//Establish mappingsNr_process + +;//number of processes plus 1List_add (&proc_list, & (Proc->list_link));//Add a process to the list of processes} local_intr_restore (Intr_flag);//7. Everything is ready to wake the child processWakeup_proc (proc);//8. Returns the PID of the subprocessret = proc->pid;fork_out:returnRet;bad_fork_cleanup_kstack:put_kstack (proc); Bad_fork_cleanup_proc:kfree (proc);GotoFork_out;}
Exercise 3 Understanding proc_run and how it invokes the function that completes the process switch

Here I start with the Proc_init () function. Because the previous proc_init () function has completed the initialization of the Idleproc kernel thread and the Initproc kernel thread. So at the end of Kern_init (), it wakes up the NO. 0 idle process through Cpu_idle (), and before analyzing the Proc_run function, we analyze the dispatch function schedule ().
schedule()The code is as follows:

Voidschedule (void) {bool Intr_flag; list_entry_t*le,*last; struct PROC_STRUCT*next= NULL;    Local_intr_save (Intr_flag); {current->need_resched =0; Last= (current = = Idleproc)?        &proc_list: & (Current->list_link); Le = Last; Do{if(Le = List_next (le))! = &proc_list) {Next= Le2proc (Le, List_link);if(Next- State= = proc_runnable) { Break; }            }        } while(Le! = Last);if(Next= = NULL | |Next- State! = proc_runnable) {Next= Idleproc; }Next->runs + +;if(Next! = current) {Proc_run (Next); }} local_intr_restore (Intr_flag);}

It is easy to read its code logic, which is a FIFO scheduler that performs the following procedures:

    • 1, set the current kernel thread current->need_resched to 0;
    • 2. In the proc_list queue, look for the next thread or process in the ready state next;
    • 3. After finding such a process, call the Proc_run function, save the current execution field (process context), restore the execution site of the new process, and complete the process switch.

That is schedule , the function finds only one initproc kernel thread in the ready state by locating the proc_list process queue. Then through proc_run and further switch_to function to complete the two execution scene switching.

OK, now go to the key proc_run function, the code is as follows:

void proc_run(struct proc_struct *proc) {    if (proc != current) {        bool intr_flag;        proc;        local_intr_save(intr_flag);        {            proc;            KSTACKSIZE);            lcr3(next->cr3);            switch_to(&(prev->context), &(next->context));        }        local_intr_restore(intr_flag);    }}

So let's analyze This code:

    • 1, let current point to the next kernel thread initproc;
    • 2, set the Task status section TS in the privilege state 0 under the stack top pointer esp0 for next kernel thread Initproc core stack top, namely Next->kstack + kstacksize;
    • 3, set the value of the CR3 register to the next kernel Thread initproc page directory table start address NEXT->CR3, which is actually the completion of the process between the page table switch;
    • 4, by the switch_to function to complete the specific two threads of the execution of the scene switch, that is, switching registers, when the switch_to function after the "ret" command, the switch to Initproc executed.

Let's take a closer look at this switch_to function, the main code is as follows:

Switch_to:# switch_to (from, to)    # Save from ' s registersMovl4(%esp),%eax          # eax points to fromPopl0(%eax)# save EIP!poplMovl%esp,4(%eax) MOVL%EBX,8(%eax) MOVL%ecx, A(%eax) MOVL%edx, -(%eax) MOVL%esi, -(%eax) MOVL%edi, -(%eax) MOVL%EBP, -(%eax)# Restore to ' s registersMovl4(%esp),%eax          # not 8 (%ESP): Popped return address already                                # EAX now points toMovl -(%eax),%EBPMovl -(%eax),%ediMovl -(%eax),%esiMovl -(%eax),%edxMovl A(%eax),%ecxMovl8(%eax),%EBXMovl4(%eax),%espPushl0(%eax)# push EIPRet

First, save the execution site of the previous process, that is, movl 4(%esp), %eax and popl 0(%eax) two lines of code.
Then the next seven instructions are as follows:

 MOVL %esp , 4  (%eax ) movl %ebx , Span class= "Hljs-number" >8  (%eax ) movl %ecx< /span>, 12  (%eax ) MOVL %edx , 16  (%eax ) movl %esi , 20  (%eax ) movl %edi , 24  ( Span class= "hljs-variable" >%eax ) movl %ebp , 28  (%eax )  

These instructions complete the other 7 registers in the previous process to context the corresponding domain in. At this point the execution site of the previous process is saved.

The next step is to restore the execution site to a process, which is actually the inverse of the above-mentioned preservation process, that is, from the context of the high address of the domain EBP start, one by one to assign the value of the relevant domain to the corresponding register.

In fact, the context of the pushl 0(%eax) next process to execute the command address CONTEXT.EIP placed on the top of the stack, so that the next execution of the last instruction "ret", the contents of the stack will be assigned to the EIP register, so switch to the next process to execute, That is, the current process is already the next process, thus completing the process switching.

Operating system Ucore LAB4 Experimental report

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.