1. Memory distribution
Attach one more, descriptor table.
Let 's talk about the contents of the Global descriptor:
Each item is 8 bytes.
The first item is full 0 and is not used.
The second item is the bucket descriptor, dt=1,dpl=00, the code snippet descriptor, the base address is 0, and the segment bounds is 16MB.
The third item is the bucket descriptor, dt=1,dpl=00, the data segment descriptor, the base address is 0, and the segment bounds is 16MB.
The fourth item is full 0 and is not used.
The fifth item is the system segment descriptor, dt=0,dpl=00, the task status segment of process 0, the address of the TSS that points to process 0, and the segment boundary is the length of the TSS of process 0.
The sixth item is the system segment descriptor, dt=0,dpl=00, The local descriptor of process 0, the address of the base address to the LDT of process 0, and the length of the LDT of process 0 for the segment boundary.
Seventh after the analogy process 1 process 2 ...
Finally formed such as:
The interrupt descriptor descriptor is as follows:
Each entry is a door descriptor, divided into three types, one is the interrupt gate, type 110,DPL is 00. The second is the trap gate, type 111,DPL is 00. The third is the system gate, type 111,DPL is 11. Seletor are 0x08, the code snippet descriptor is selected, the base address is 0, and the segment bounds is 16MB. The offset is the offset of the specific interrupt handling function.
The LDT of process 0 is as follows:
The first item is all zeros.
The second item is the bucket descriptor, dt=1,dpl=11, the code snippet descriptor, the base address is 0, and the segment bounds is 640KB.
The third item is the bucket descriptor, dt=1,dpl=11, the data segment descriptor, the base address is 0, and the segment bounds is 640KB.
The LDT of Process 1 is as follows:
The first item is all zeros.
The second item is the bucket descriptor, dt=1,dpl=11, the code snippet descriptor, the base address is 64MB, and the segment bounds is 640KB.
The third item is the bucket descriptor, dt=1,dpl=11, the data segment descriptor, the base address is 64MB, and the segment bounds is 640KB.
The LDT of Process 2 is as follows:
The first item is all zeros.
The second item is the bucket descriptor, dt=1,dpl=11, the code snippet descriptor, the base address is 128MB, and the segment bounds is 640KB.
The third item is the bucket descriptor, dt=1,dpl=11, the data segment descriptor, the base address is 128MB, and the segment bounds is 640KB.
And so on
However, Process 2 later executed the following code:
void init (void) {int pid,i; ... if (! ( Pid=fork ())) {//process 1 Create process 2close (0), if (Open ("/ETC/RC", o_rdonly,0) _exit (1); Execve ("/bin/sh", ARGV_RC,ENVP_RC); _exit (2);} if (pid>0) while (pid! = Wait (&i))/* nothing */; ...}
so:The Shell's Ldt is as follows:
The first item is all zeros.
The second item is the bucket descriptor, dt=1,dpl=11, the code snippet descriptor, the base address is 128MB, and the segment bounds is the actual length of the shell program.
The third item is the bucket descriptor, dt=1,dpl=11, the data segment descriptor, the base address is 128MB, and the segment bounds is 64MB (so that the page catalog entry takes up the position from 32~48).
2, the following introduction 80386 register
The kernel state, the CS selector ti=0, is selected from the GDT table, the rpl=00, the kernel state, the descriptor index is 1, and the second code snippet descriptor in the GDT table is selected.
The kernel state, Ss,ds,es,fs,gs selector ti=0, represents the selection from the GDT table, the rpl=00, the kernel state, the descriptor index is 2, and the third data segment descriptor in the GDT table is selected.
The user state, CS selector Ti=1, represents the selection from the LDT table, the rpl=11, the user state, the descriptor index is 1, and the second code snippet descriptor in the LDT table is selected.
The user state, the Ss,ds,es,fs,gs selector Ti=1, represents the selection from the LDT table, the rpl=11, the user state, the descriptor index is 2, and the third data segment descriptor in the LDT table is selected.
The LDTR selector, Ti=1, represents the selection from the GDT table, rpl=00, kernel State, descriptor index and process, process 0 Descriptor index is 3, Process 1 Descriptor index is 5, select fourth in the GDT table, or sixth system segment descriptor. In turn.
TR Selector, Ti=1, represents the selection from the GDT table, rpl=00, kernel State, descriptor index and process-related, Process 0 Descriptor index is 4, Process 1 Descriptor index is 6, select fifth in the GDT table, or seventh system segment descriptor. In turn.
Descriptor cache registers and LDTR cache registers and TR cache registers, 0-31 holds the first address of the segment, 0-19 storage segment bounds, and 0-11 storage segment properties. is the corresponding bucket descriptor and the system segment descriptor (also 64 bits).
The gdtr,0~31 bit holds the base address of the GDT (Global Descriptor Chart) in the memory allocation graph, and the 0~15 bit holds the bounds of the GDT (global descriptor) in the memory allocation graph.
The idtr,0~31 bit holds the base address of the IDT (Interrupt descriptor chart) in the memory allocation graph, and the 0~15 bit holds the bounds of the IDT (Interrupt descriptor chart) in the memory allocation graph.
3. The nature of privilege-level switching:
Interrupt int 0x80 enters privilege level 0 from privileged Level 3 and holds registers such as Ss,esp,eflags,cs,eip in the stack of privileged level 0 (TSS esp0,ss0), Iret returns privilege level 3 from privileged level 0.
since seletor are 0x08, the CS selector is the kernel state, and the descriptor is taken from the GDT, so the interrupt handler is already in the 0 privilege level, kernel state. Pressure stack is SS also 0x10, later Ds,es,fs,gs also became 0x10.
So the nature of the privilege-level change is that the CS,DS,ES,FS,GS,SS is different, the privilege level 0 obtains the descriptor from the GDT, the preceding registers 3 bits 000, the descriptor privilege level is 00, the privilege Level 3 obtains the descriptor from the LDT, the preceding registers 3 bits 111, The Descriptor privilege level is 11.
4, the nature of process switching:
Saves the current register state in the TSS of the current process and restores the register of the process to be switched to the content in the TSS of the process to be switched. To focus on understanding the LDTR selector, tr selector. The LDTR selector finds the LDTR cache of the current process in the GDT table, which is the base address and bounds of the LDT table. The TR selector finds the current process's TR cache in the GDT table, which is the base address and bounds of the TSS table.
5, the nature of the interruption:
Interrupts and privilege-level switching are similar, except that interrupts can occur in the user state or kernel state, while privileged switching occurs only in the user state. When the interrupt occurs in the kernel state, the C s,esp,eflags,cs,eips that is pressed into the privileged level 0 stackis the register value of the kernel state.
6, the nature of the creation process:
Get a page of memory such as:
(1) Task_struct is the data that replicates the parent process. Modifies the data in PID,FATHER,TSS Eip,cs points to the downstream code that the parent process will execute. The data in the LDT is inherited directly and is modified later.
(2) Set sub-process LDT code snippet and data segment base address is nr * 64MB, segment boundary is 640KB.
(3) Set the page directory entry for the process, process 0 is the first item; Process 1 is the 16th item and Process 2 is the 32nd item. Get a page of memory first, and then copy the parent process's page table entries into this memory. This way the parent-child process shares the actual memory.
(4) The child process also inherits the PWD,ROOT,FILP of the parent process. Count plus 1.
(5) Set the Tss,ldt in the tast_stuct in the GDT system segment descriptor. Place the base address and paragraph bounds of the Tss,ldt into the GDT.
The parent Process Fork returns a non-0, and the child process fork returns 0, but all of the code behind the fork can be distinguished by the IF statement.
7, the nature of the implementation process:
first releases the original process page catalog entries and page table entries, and then re-establishes the page Catalog entries and page table entries, and finally returns to user space execution. For specific reference, the shell process is loaded through Process 2, detailed execve.
8, the nature of process scheduling:
One is the clock interrupt, every 10ms, but only when the clock is in the user state, the process switch will occur.
One is that the process actively calls Schedue () in the kernel state.
9. Schedue function:
Find out counter the largest ready process run. If no process is ready, switch to process 0 idle. If there is a ready process but the counter value is 0, then the time slice is redistributed.
10, process status Task_interruptible and task_uninterruptible.
Task_interruptible If the current process receives a signal, then Schedue will turn the process into Task_run. But task_uninterruptible, the signal is not heeded.
task_uninterruptible can only be awakened by WAKE_UP and become task_run.
The process is usually set to task_interruptible when you pause . The process is set to task_uninterruptible when Sleep_on .
11, the nature of the signal
Send signal: Is the signal of the target process, the corresponding setting is 1.
Receive signal: Detects whether the current process is receiving a signal before the system call returns, or whether the current process is receiving a signal, after the clock interrupt occurs, before the end of the service program execution.
The signal handler is detected based on the signal, and the corresponding signal processing function is found Current->sigaction + signr-1 according to the signal.
The signal handler function is executed after the system call is returned, and then to the next instruction where the system call occurs. Refer to the art of Linux kernel design-interprocess communication-signaling.
12, the nature of the pipeline
The essence of the pipeline is that the operating system opens up a page of memory for each pipe in memory, giving this page memory the properties of the file. This page of memory is shared by two processes.
Inode->i_size=get_free_page ();
F[0]->f_inode = F[1]->f_inode = Inode;
13, the essence of Put_page:
unsigned long put_page (unsigned long page,unsigned long address)
The address is a linear address that page points to.
After the function is executed, a mapping of the address from the linear address to the page is established. This means that the page Catalog entry and page table entries are established. Then the linear address--paging mechanism--the address of the actual physical page.
Linux 0.11 Summary