200 likes | 408 Views
Project 2 Roadmap. Segmentation Review. Intel docs, fig. 3-1 and 3-5. Spawn(). Starts a user program in src/geekos/user.c triggered by SYS_SPAWN Read_Fully() read an executable file from disk into memory Parse_ELF_Executable() fill Exe_Format data structure; (Project 1)
E N D
Segmentation Review • Intel docs, fig. 3-1 and 3-5
Spawn() Starts a user program • in src/geekos/user.c • triggered by SYS_SPAWN • Read_Fully() • read an executable file from disk into memory • Parse_ELF_Executable() • fill Exe_Format data structure; (Project 1) • ignore the bogus program headers (size=0) • Load_User_Program() • will set up the memory image for the new process and create a User_Context with the loaded program • Start_User_Thread() • with the new User_Context
Load_User_Program() Prepares a new address space for the program and creates a User_Context • in src/geekos/userseg.c • allocate the memory image of the new process • find highest virtual address: scan Exe_Format • find args size: • Get_Argument_Block_Size() • this is not sizeof(Argument_Block) ! • size = • Round_Up_To_Page(highest virtual address) + • DEFAULT_USER_STACK_SIZE + • args size • create the User_Context… • Fill in remaining User_Context fields
Create_User_Context() Allocates space for a User_Context,fill in its fields. User_Context stores all the information needed to setup and run a user thread • in src/geekos/userseg.c • create an LDT for the process • add a descriptor to the GDT that describes the location of the LDT • create a selector that contains the location of the LDT descriptor within the GDT • create descriptors for the code and data segments of the user program and add these descriptors to the LDT • create selectors that contain the locations of the two descriptors within the LDT
struct Segment_Descriptor ldt[0] struct Segment_Descriptor ldt[1] struct Segment_Descriptor *ldtDescriptor ushort_t ldtSelector ushort_t csSelector LDT descriptor ushort_t dsSelector int stackAddr int programSize char * program 1 Create an User_Context structure; it will store all the information that will be needed to setup and run the user thread Malloc() 2 Allocate an LDT descriptor in the GDT for the process Allocate_Segment_Descriptor() 3 Initialize the LDT descriptor in GDT with the location of the LDT Init_LDT_Descriptor() 4 Create a selector that contains the location of the LDT descriptor within the GDT Selector() 5 Initialize the descriptors in LDT as code/data descriptors Init_Code_Segment_Descriptor()/Init_Data_Segment_Descriptor 6 Create selectors that contain the locations of the two descriptors within the LDT Selector() User_Context 1 Create_User_Context() Selector 5 5 GDT 6 4 6 4 Selector 3 2 6 Selector
Start_User_Thread Create a thread, setup the stack to look as if it was interrupted, make it runnable. • in src/geekos/kthread.c • Create_Thread() • call Setup_User_Thread() which will push values (specified in description) • Look at Setup_Kernel_Thread()for similar code • Make_Runnable_Atomic()
Command Line Arguments In Load_User_Program(), create an Argument_Block data structure and attach it to the process image. This data structure contains the argc and argv arguments that are passed to the main() function of the user program • Get #of bytes and argc from Get_Argument_Block_Size() • Call Format_Argument_Block() to • build Argument_Block data structure in user memory • fix argv up (make all user space pointers)
System Calls • INT90 • put args in registers on user side • recover them on kernel side • call Sys_xxx accordingly • return result/error code • Use g_CurrentThread to get info about current thread
Sys_Null • Just add a print statement in syscall.c • Your first test for user mode: • spawn /c/null.exe
Sys_Exit • simple call to Exit() • but funs called from Exit() must clean up the thread • Free_Segment_Descriptor • Free userContext, memory space allocated for the program
Sys_PrintString • Copy_From_User() the string • Put_Buf()
Sys_GetKey • Wait_For_Key() • the shell takes care of the rest • see libc/conio.c
Sys_SetAttr/Sys_GetCursor/Sys_PutCursor • straightforward calls to name-similar kernel funs • Sys_GetCursor() requires a Copy_To_User() !
Sys_Spawn • Calls Spawn() • Command needs a Copy_From_User() !
Sys_Wait • Wait for specified PID • Use Join()
Sys_GetPID • just return current thread’s PID
Copy_From_User/Copy_To_User • Caller allocates space (dstInKernel) • Validate memory pointer • is within bounds? • convert • If yes copy • Make generic, not specific to strings • Ensure proper ‘\0’ termination for SYS_PRINTSTRING and SYS_SPAWN
struct Segment_Descriptor ldt[0] struct Segment_Descriptor ldt[1] struct Segment_Descriptor *ldtDescriptor ushort_t ldtSelector . . . ushort_t csSelector LDT descriptor ushort_t dsSelector . . . User_Context GDT ldtSelector