Background
大体流程如下图所示,显然这时候start_process无法被调度到。
然后start_process 里面load .out文件
(.o文件就是对象文件,是可重定向文件的一种,通常以ELF格式保存,里面包含了对各个函数的入口标记,描述,当程序要执行时还需要链接(link).链接就是把多个.o文件链成一个可执行文件out)
ELF格式
先创造pagetable,然后加载headr(记录结构)到内存,然后解析data,bss,text到内存,然后初始化栈。
如何进入和退出内核态
通过栈来保存寄存器的值。
这就是大体背景
1.参数传递
简单说就是把参数压栈
因为这个最初的函数不会return
2.系统调用
通过int 触发,然后有系统调用编号 NUMBER
加 0-3 个参数 ARG[0-3]。
这些参数由调用者通过 pushl
指令直接压入栈,syscall_handler()
中,要从参数 interrupt frame 的 ESP
中提取这些参数。
然后就是各种操作了
exit syscall就是把这个进程退出(因为pintos一个进程里只能有一个线程),然后设置这个进程的错误码
大体结构如图
然后就是文件系统调用了
因为目前文件系统不支持并发读取,所以我在文件系统加了一把大锁,然后进行读取,这一部分就是调用api,没什么好说的
就是我们要维护一下fd和file直接的关系
所以我们就要在thread上做一个结构,file_list来做
然后我们要在进程执行过程中锁住可执行文件,不让他被修改,也就是load时上锁,然后在当前线程上记录一下文件,然后在进程退出时,解锁,或者关闭就行。
3.访存检查
第一种在访问用户指针的内存前先做合法性检查:地址是否属于用户内存区域(小于 PHYS_BASE
)以及地址是否属于当前进程的内存区域;第二种是仅做前者的检查然后就访问,如果不合法会引发 page fault,然后再处理这个异常。
如果在内核态下触发page fault我们就认为是访存不合法。
我们现在可以通过page_fault来验证,利用mmu
因为这个解引用在内核里面,然后在用户态,解引用会自动page faut分配,而内核态则不会!也就是说传入的东西,要先在用户态分配,而不是一个非法指针,不是属于当前进程的内存区域。