yuyang66
yuyang66
bug出现详细过程: 父进程在调用env_alloc的过程中,需要进行4次函数调用,如下图:  这么长的代码不必全部理解,我们只需要知道跳回的地址ra分别被保存在了虚拟地址: 0x7f3fdfdc 0x7f3fdfc0 0x7f3fdf80 让我们来看下此时用户栈的情况:  在sys_env_alloc函数中,操作系统使用内核栈,不再访问父进程的用户栈,而子进程应该继承的,也应该是此时的用户栈。但是,子进程运行时继承的用户栈却和此时的用户栈有很大不同。 我们继续追踪程序运行过程,来寻找原因: 在从sys_env_alloc跳回的过程中,栈指针上推:  然后,为父子进程添加COW保护的时候,父进程调用了sys_mem_map函数,又向用户栈写入数据,而此时,用户栈还没有被COW保护起来:  我们可以看到,0x7f3fdf80这个地址又再次被写入数据,这样,之前的ra跳回信息就被覆盖掉了。 等到子进程运行的时候,我们首先来看一下他的用户栈的状态:  很明显,和进行sys_env_alloc函数时的用户栈有很大不同,其中就有0x7f3fdf80这个跳回地址被覆盖: 然后,如下图,子进程的跳回就无法正确执行,最后,跳到了一个奇怪的地址:0x0000500c ...
解决方法是:在sys_env_alloc中进行对父子进程添加COW保护:代码: (需要注意:set_pgfault_handle这一步一定要在sys_env_alloc之前) int sys_env_alloc(void) { // Your code here. int r; struct Env *e; struct Page *p; Pte *ppte; u_long i; bcopy((void *)KERNEL_SP - sizeof(struct Trapframe),&(curenv->env_tf),sizeof(struct Trapframe)); env_alloc(&e,curenv->env_id); bcopy(&(curenv->env_tf),&(e->env_tf),sizeof(struct Trapframe));...