顺序如下:
调用alloc_proc,首先获得一块用户信息块。
为进程分配一个内核栈。
复制原进程的内存管理信息到新进程(但内核线程不必做此事)
复制原进程上下文到新进程
将新进程添加到进程列表
唤醒新进程
返回新进程号
proc = alloc_proc();//分配线程控制块
proc->cr3 = boot_cr3;//切换页基址
setup_kstack(proc);//为线程分配一页空间
copy_mm(clone_flags,proc);
copy_thread(proc,stack,tf);//将相关寄存器填到页上
proc->pid = get_pid();//得到新的线程号pid
hash_proc(proc);//把线程挂在hash链表上 作用:加速查找线程
list_add(proc_list.prev,&(proc->list_link));//挂在调度链表上
wakeup_proc(proc);//唤醒线程(更改线程状态)
return proc->pid;
相关函数:
setup_kstack(struct proc_struct *proc) {
struct Page *page = alloc_pages(KSTACKPAGE);
if (page != NULL) {
proc->kstack = (uintptr_t)page2kva(page);
return 0;
}
return -E_NO_MEM;
}
copy_thread(struct proc_struct *proc, uintptr_t esp, struct trapframe *tf) {
proc->tf = (struct trapframe *)(proc->kstack + KSTACKSIZE) - 1;
*(proc->tf) = *tf;
proc->tf->tf_regs.reg_eax = 0;
proc->tf->tf_esp = esp;
proc->tf->tf_eflags |= FL_IF;
proc->context.eip = (uintptr_t)forkret;
proc->context.esp = (uintptr_t)(proc->tf);
}
wakeup_proc(struct proc_struct *proc) {
assert(proc->state != PROC_ZOMBIE && proc->state != PROC_RUNNABLE);
proc->state = PROC_RUNNABLE;
}