JOS中具有写时拷贝的fork设计
如果不高清fork的设计思想,是无法实现正确高效的fork。
JOS中写时拷贝的fork设计
内核态
kern/syscall.c/sys_exofork():
- 分配新的Env结构体
- 拷贝父进程的trapframe(主要为寄存器信息)
- 设置eax寄存器为0(eax存放返回值)
- 返回新进程的eid
kern/syscall.c/sys_env_set_pgfault_upcall():
- 在Env结构体中设置upcall,本质:
1
env->env_pgfault_upcall = _pgfault_upcall
kern/trap.c/pgfault_handler():
- 内核缺页,panic
- 如果设置了
env_pgfault_upcall
,则调用_pgfault_upcall
。
用户态
lib/fork.c/fork():
- set_pgfault_handler(),设置用户态异常栈,以及设置用户态异常入口
_pgfault_upcall
- sys_exo_fork(),创建子进程
- 子进程返回,父进程继续
- duppage(),复制父进程地址空间到子进程,实现共享内存,设置COW
- sys_env_set_pgfault_upcall(),为子进程设置户态异常入口
_pgfault_upcall
- sys_env_set_status(),修改子进程状态
lib/pgfault.c/set_pgfault_handler():
- 如果没有设置用户态异常栈(异常处理函数运行的地方),设置用户态异常栈
- 设置用户态异常入口
_pgfault_upcall
- 只会被父进程调用
lib/fork.c/duppage():
- 把虚地址页映射到制定进程的地址空间
lib/pfentry.S/_pgfault_upcall
- 调用lib/fork.c/pgfault()
lib/fork.c/pgfault():
- 如果页异常的页是COW属性
- 创建临时页,属性可读写,原数据拷贝到临时页,临时页映射到页异常进程的该页