一、进程相关函数
在做lab3的实验时,发现函数嵌套的情况很多,首先整理这一块的逻辑。
箭头表示函数调用
1.初始化:
- 申请envs[]的空间;初始化env_free_list(把空闲进程env_status设置为ENV_FREE)
2.创立进程:设置env_pri
- env_alloc():
- 从env_free_list取出一块空闲进程;
- 设置env_id,env_status,env_parent_id,env_tf.cp0_status,env_tf.regs[29]
- env_setup_vm():
- 为进程创建一页页目录,并建立好自映射
- 设置env_pgdir,env_cr3
-
load_icode():
- 为进程申请一页作为栈,并建立好映射
- 设置env_tf.pc(为load_elf返回的binary的入口)
-
load_elf()/load_icode_mapper():
-
以一个段(segment)为单位,把binary(进程的内容的二进制镜像)的内容复制到所在内存的虚拟地址
-
(load_elf负责找入口,mapper负责copy)
-
3.切换进程
- 保存当前进程的上下文,设置env_tf,env_tf.pc
- 恢复要启动的进程上下文,并启动新进程,设置env_status,env_pgdir,操作了env_tf,env_id
二、进程控制块(PCB)
进程控制块(PCB) 是系统为了管理进程设置的一个专门的数据结构,用它来记录进程的外部特征,描述进程的运动变化过程。系统利用PCB 来控制和管理进程,所以 PCB 是系统感知进程存在的唯一标志 。
首先贴出PCB的构成。
1 struct Env { 2 /* Trapframe 结构体的定义在include/trap.h 中, 3 * env_tf 的作用就是在进程因为时间片用光不再运行时, 4 * 将其当时的进程上下文环境保存在env_tf 变量中。 5 * 当从用户模式切换到内核模式时,内核也会保存进程上下文, 6 * 因此进程返回时上下文可以从中恢复。 7 */ 8 struct Trapframe env_tf; // Saved registers 9 10 LIST_ENTRY(Env) env_link; // Free LIST_ENTRY 构造空闲进程链表。 11 12 u_int env_id; // Unique environment identifier 13 14 /*该变量存储了创建本进程的进程id。 15 *这样进程之间通过父子进程之间的关联可以形成一颗进程树。 16 */ 17 u_int env_parent_id; // env_id of this env's parent 18 /*env_status : 该变量只能在以下三个值中进行取值: 19 – ENV_FREE : 表明该进程是不活动的,即该进程控制块处于进程空闲链表中。 20 21 – ENV_NOT_RUNNABLE : 表明该进程处于阻塞状态,处于该状态的进程往往在 22 等待一定的条件才可以变为就绪状态从而被CPU 调度。 23 24 – ENV_RUNNABLE : 表明该进程处于就绪状态,正在等待被调度,但处于RUNNABLE 25 状态的进程可以是正在运行的,也可能不在运行中。*/ 26 u_int env_status; // Status of the environment 27 28 Pde *env_pgdir; // Kernel virtual address of page dir 这个变量保存了该进程页目录的虚拟地址。 29 30 u_int env_cr3;// 这个变量保存了该进程页目录的物理地址。 31 32 LIST_ENTRY(Env) env_sched_link;//这个变量来构造就绪状态进程链表。 33 34 u_int env_pri;//这个变量保存了该进程的优先级。 35 36 };