从整体上讲,exec
系统调用创建了用户部分的地址空间。
具体地讲,做了9件事:
- 调用
nami
函数打开有名字的二进制路径path
; - 读取
ELF
文件头; - 检查该文件是否是
ELF
文件; - 调用
proc_pagetable
来分配新的无用户映射的页表; - 调用
uvmalloc
为每个ELF段分配内存; - 调用
loadseg
将每个段加载进内存; - 分配和初始化用户栈;
- 将新内存映像提交给新页表;
- 清空旧页表;
谁创建了用户部分的地址空间?
exec
系统调用
exec
系统调用如何分配和初始化用户栈?
- 只分配一个栈页;
- 将参数字符串拷贝到栈顶,一次拷贝一个参数,在
ustack
中记录指向参数的指针; - 在传递给
main
函数的argv
列表末尾放入一个null
指针; - 刚好在栈页的下方放入一个不可访问页;
栈保护页有什么作用?
- 保证那些尝试使用超过一个页的程序都失败;
- 允许
exec
处理过大的参数;
当exec
调用copyout
函数将参数拷贝到栈上时,copyout
就会注意到目的页是不可访问的,返回-1