//拷贝父进程本身所占资源给子进程 static int32_t copy_process(struct task_struct* child_thread,struct task_struct* parent_thread){ //内核缓冲区,作为父进程用户空间的数据复制到子进程用户空间的中转 void* buf_page = get_kernel_pages(1); if(buf_page == NULL){ return -1; } //a 复制父进程的pcb、虚拟地址位图、内核栈到子进程 if(copy_pcb_vaddrbitmap_stack0(child_thread,parent_thread) == -1){ return -1; } //b 为子进程创建页表,此页表仅包括内核空间 child_thread->pgdir = create_page_dir(); if(child_thread->pgdir == NULL){ return -1; } //c 复制父进程进程体及用户栈给子进程 copy_body_stack3(child_thread,parent_thread,buf_page); //d 构建子进程thread_stack和修改返回值pid build_child_stack(child_thread); //e 更新文件inode的打开数 update_inode_open_cnts(child_thread); mfree_page(PF_KERNEL,buf_page,1); return 0; }
void do_fork_vm (process_t *parent, process_t *child) { //printf ("FORK_VM: forking memory tables\n"); // Create a page directory if (create_page_dir (child)) { panic ("Cant setup page dir for new child!\n"); } //printf ("FORK_VM: preparing copy on write\n"); //Setup pagetables prepare_copy_on_write (parent, child); //printf ("FORK_VM: setting mem-blocks\n"); //Set the vm_blocks in proc table child->vm_code.vm_start = parent->vm_code.vm_start; child->vm_code.vm_end = parent->vm_code.vm_end; child->vm_code.vm_flags = parent->vm_code.vm_flags; child->vm_data.vm_start = parent->vm_data.vm_start; child->vm_data.vm_end = parent->vm_data.vm_end; child->vm_data.vm_flags = parent->vm_data.vm_flags; child->vm_stack.vm_start = parent->vm_stack.vm_start; child->vm_stack.vm_end = parent->vm_stack.vm_end; child->vm_stack.vm_flags = parent->vm_stack.vm_flags; child->vm_kernel_stack.vm_start = parent->vm_kernel_stack.vm_start; child->vm_kernel_stack.vm_end = parent->vm_kernel_stack.vm_end; child->vm_kernel_stack.vm_flags = parent->vm_kernel_stack.vm_flags; //printf ("FORK_VM: done\n"); }
void vm_setup_init_process (process_t *init_proc, Elf32_Phdr *pht, int pht_entries, loaded_module_t *init_mod) { page_frame_t *stack_page; page_frame_t *kernel_stack_page; int i; unsigned int data_min = 0xffffffff; unsigned int data_max = 0; unsigned int code_min = 0xffffffff; unsigned int code_max = 0; // // Create a page directory // if (create_page_dir (init_proc)) { panic ("Cant setup page dir for init task!\n"); } // // HAS TO CHECK PHT AND MAP ACCORDINGLY!! // //Get page table and insert loaded pages into it for (i = 0; i < pht_entries; i++) { if (pht[i].p_flags & PF_X) { //It's a code entry if (pht[i].p_memsz > PAGE_SIZE) panic ("INIT bigger tham one page, not implemented yet!"); if (pht[i].p_memsz > 0) { code_max = MAX(code_max,(pht[i].p_vaddr + pht[i].p_memsz)); code_min = MIN(code_min,pht[i].p_vaddr); map_page (init_proc, init_mod->page_frames->page_frame_nr * PAGE_SIZE, pht[i].p_vaddr, PAGE_PRESENT | PAGE_USER); } } else { //It's a data entry if (pht[i].p_memsz > PAGE_SIZE) panic ("INIT bigger tham one page, not implemented yet!"); if (pht[i].p_memsz > 0) { data_max = MAX(data_max,(pht[i].p_vaddr + pht[i].p_memsz)); data_min = MIN(data_min,pht[i].p_vaddr); map_page (init_proc, init_mod->page_frames->page_frame_nr * PAGE_SIZE, pht[i].p_vaddr, PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER); } } } //Set the areas in proc table init_proc->vm_code.vm_start = code_min; init_proc->vm_code.vm_end = code_max; init_proc->vm_code.vm_flags = VM_READONLY | VM_CODE; init_proc->vm_data.vm_start = data_min; init_proc->vm_data.vm_end = data_max; init_proc->vm_data.vm_flags = VM_READWRITE; //Setup a new stack page stack_page = get_free_page (); kernel_stack_page = get_free_page (); init_proc->tss.ss0 = DS_SELECTOR; init_proc->tss.esp0 = PROC_KERNEL_STACK_TOP; init_proc->tss.ss = USER_DS_SELECTOR; init_proc->tss.esp = USER_STACK_TOP; map_page (init_proc, kernel_stack_page->page_frame_nr * PAGE_SIZE, PROC_KERNEL_STACK_TOP, PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER); map_page (init_proc, stack_page->page_frame_nr * PAGE_SIZE, USER_STACK_TOP, PAGE_PRESENT | PAGE_WRITEABLE | PAGE_USER); //vm addresses are linear init_proc->vm_kernel_stack.vm_start = PROC_KERNEL_STACK_TOP & PHYS_PAGE_MASK; init_proc->vm_kernel_stack.vm_end = (PROC_KERNEL_STACK_TOP & PHYS_PAGE_MASK) + PAGE_SIZE; init_proc->vm_kernel_stack.vm_flags = VM_READWRITE; init_proc->vm_stack.vm_start = USER_STACK_TOP & PHYS_PAGE_MASK; init_proc->vm_stack.vm_end = (USER_STACK_TOP & PHYS_PAGE_MASK) + PAGE_SIZE; init_proc->vm_stack.vm_flags = VM_READWRITE; map_standard_pages (init_proc); }