jos lab 2-3函数介绍
本文章主要用于另一篇文章的引用
Lab2
各个函数功能:
boot_alloc(uint32_t n):分配一个PGSIZE向上取整的内存,返回其虚拟地址
注:从内存的end开始分配(查资料看到说end是bss段最后的位置),这各函数维护了一个下个空闲地址的指针(nextfree),因此总能分配下一个空闲地址。这里要说一下为什么这样分配不会产生问题,因为调用到此函数的时候,系统还未占用其他大部分地址,因此不会产生影响,之后的页分配都是使用page_alloc了。
page_init():初始化page,将未使用的page加入到free_page链表中
注:提示中说明了 1.第0页被占用 2.io hole 不能被分配3.在extmem区域还有一部分已经被占用
page_alloc(flag):从free_list中取出一页,当flag=true时,初始化该页内存
注:返回的是pageInfo
page_free( struct PageInfo *pp):将页加入到free_list中
---------------------------------------------------------------------------
其中有四个宏定义:page2pa、page2va、pa2page、va2page
它们分别是将page(PageInfo)转换成物理地址、将page[i]转换成虚拟地址以及对应的转换回来。
主要说一下page2pa:他是用(page[i]-pages(page的起始地址) ) * 4k = 虚拟地址
pgdir_walk:传入虚拟地址,返回它所在的页首地址
注:通过虚拟地址,获取其页目录位置,取得此地址的值(页表物理地址),将其转换为页表首地址(KADDR),再从页表中找到所需要的页表项
boot_map_region:把虚拟地址和物理地址的联系放到页的首地址,并设置权限等信息
注:此时因为物理地址后12位并没有什么作用,因此存放了权限、是否在内存中
等信息。
page_insert:把指定的物理地址和虚拟地址之间的联系放到页的首地址(如果虚拟地 址已经有映射,删除之前的映射,添加新的)
注:传入页目录 和 pageInfo 以及一些条件参数,就可以通过计算(pageinfo-->虚拟地址-->页目录)得到所需结果
page_lookup:根据虚拟地址,找到相应的page(pageInfo)的位置
注:虚拟地址-->页目录项-->物理地址(页目录项的值)-->page(用pa2page计算)
page_remove:虚拟地址va和物理页的映射关系删除
注: pp_ref每次减1,当值为0时,才将page收回,并将pp_ref置0
===============================================================================
Lab3
各个函数的功能
env_init:初始化env结构体链表,将其所有都加入到page_free_list中,初始化结构体中一些变量的信息(设为默认值)
env_setup_vm:为进程分配内存空间,并单独的分配page directory
注:根据pageinfo 申请一个新的页面,以此来生成新的页目录。
UTOP之上完全拷贝kern_pgdir, 因为所有用户环境的页目录表中和操作系统相关的页目录项都是一样的。其UVPT处设置自己的信息。
region_alloc: 为运行环境开辟len byte大小的物理空间,并将va虚拟地址开始的len长度大小的空间和物理空间建立映射关系
注:申请了页之后,调用page_insert将相应的页插入到相应页目录下的计算得到的位置
env_alloc:从env_free_list中取出一个env,并将其属性(id之类的)初始化
load_icode:为每一个用户进程设置它的初始代码区,堆栈以及处理器标识位。每个用户程序都是ELF文件,所以我们要解析该ELF文件。
env_create:它会调用env_alloc,从env_free_list中取出一个env结构体,再通过 env_setup_vm为其初始化,申请新的页目录; 然后执行load_icode,这个函数加载elf文件(二进制文件),它会调用region_alloc为其分配页,并将虚拟地址和物理地址作出映射,load_icon之后分配进程栈,以及,将env->env_tf.tf_eip指向将执行进程函数的入口(等待env_pop_tf的调用)
Env_run:启动进程,通过env_pop_tf函数,改变env结构体中运行状态等信息(防止后来的一个进程在多个内核中运行),将env结构体中保存的寄存器中的信息加在到真正的寄存器中,接下来便执行eip所指向的内容。