yuyang66

Results 2 comments of yuyang66

bug出现详细过程: 父进程在调用env_alloc的过程中,需要进行4次函数调用,如下图: ![image](https://cloud.githubusercontent.com/assets/26699097/24344509/68a236a6-12fe-11e7-9df7-ed2b904ed7d5.png) 这么长的代码不必全部理解,我们只需要知道跳回的地址ra分别被保存在了虚拟地址: 0x7f3fdfdc 0x7f3fdfc0 0x7f3fdf80 让我们来看下此时用户栈的情况: ![image](https://cloud.githubusercontent.com/assets/26699097/24344744/78856a2e-12ff-11e7-86ca-06991072e066.png) 在sys_env_alloc函数中,操作系统使用内核栈,不再访问父进程的用户栈,而子进程应该继承的,也应该是此时的用户栈。但是,子进程运行时继承的用户栈却和此时的用户栈有很大不同。 我们继续追踪程序运行过程,来寻找原因: 在从sys_env_alloc跳回的过程中,栈指针上推: ![image](https://cloud.githubusercontent.com/assets/26699097/24344843/eff61aa4-12ff-11e7-80a8-5074e3682ea2.png) 然后,为父子进程添加COW保护的时候,父进程调用了sys_mem_map函数,又向用户栈写入数据,而此时,用户栈还没有被COW保护起来: ![image](https://cloud.githubusercontent.com/assets/26699097/24344856/ff5f8732-12ff-11e7-99a9-38df63325737.png) 我们可以看到,0x7f3fdf80这个地址又再次被写入数据,这样,之前的ra跳回信息就被覆盖掉了。 等到子进程运行的时候,我们首先来看一下他的用户栈的状态: ![37 a 87a 03 aknj2 lvvxd](https://cloud.githubusercontent.com/assets/26699097/24344865/07a395e6-1300-11e7-82d9-fe28e5dd39ce.png) 很明显,和进行sys_env_alloc函数时的用户栈有很大不同,其中就有0x7f3fdf80这个跳回地址被覆盖: 然后,如下图,子进程的跳回就无法正确执行,最后,跳到了一个奇怪的地址:0x0000500c ![par8 h 8tx97 276sr b](https://cloud.githubusercontent.com/assets/26699097/24344935/5614f756-1300-11e7-9a75-d24b6cf671f8.png)...

解决方法是:在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));...