实验二 进程与线程
马逸君 17300180070
Question 1 阅读allocproc函数,分析这个函数的原理并解释这个函数的作用。
作用:限制同时在使用中的线程数量,如果未超出,则将新申请的进程准备好,供申请者使用。
原理概述:allocproc()函数遍历进程池(进程池是一个大小为常量的进程数组),寻找状态为UNUSED
的进程,若未找到则返回0,若找到则将其状态设为EMBRYO,并对其状态进行必要的初始化工作(包
括分配进程标识符、分配内核中的栈空间、为当前调用的“陷阱帧”(trap frame)预留空间、设置寄存器现
场),以使得该进程可以投入运行。
详细原理:(见代码注释)
static struct proc*
allocproc(void) // 返回所申请到的新进程的指针,失败则返回0(空指针)
{
struct proc *p; // 用于遍历进程池的循环变量
char *sp;
acquire(&ptable.lock); // 给进程表上锁,互斥访问
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
// 遍历进程池(一个大小为常量的进程数组)
if(p->state == UNUSED) // 寻找状态为UNUSED(未用,可分配给新进程)的进程
goto found; // 若找到,则进行必要初始化工作,分配给新进程(见后)
// 未找到UNUSED进程
release(&ptable.lock); // 互斥访问过程结束,给进程表解锁
return 0; // 返回0(空指针),表示分配进程失败
found: // 找到可分配的UNUSED进程
p->state = EMBRYO; // 将其状态设为EMBRYO(“胚胎”,即将被分配给新进程)
p->pid = nextpid++; // 分配进程标识符
release(&ptable.lock); // 访问进程表结束,给进程表解锁
// 新进程的内核栈空间的分配
if((p->kstack = kalloc()) == 0){ // 内核申请物理内存,作为新进程栈空间
// kalloc()函数定义在kalloc.c中,分配一个4KB大小的物理内存的页面
p->state = UNUSED;
return 0;
// 如果申请失败,则不能分配新进程。将新进程状态恢复为UNUSED,函数返回0
}
sp = p->kstack + KSTACKSIZE; // 预留KSTACKSIZE(=4K)大小的空间
// 为新进程的陷阱帧(trap frame)预留空间
// 陷阱帧:异常发生时寄存器组的值,异常/中断处理完毕后从中读取恢复寄存器组的值并继续
执行原来过程
sp -= sizeof *p->tf; // 新进程栈空间的最高处,预留sizeof(trapframe)大小的空间
给陷阱帧
p->tf = (struct trapframe*)sp; // 设定新进程陷阱帧的指针指向这块预留空间的首地
址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
评论0