本实验依赖实验1/2/3。请把你做的实验1/2/3的代码填入本实验中代码中有“LAB1”,“LAB2”,“LAB3”的注释相应部分。
alloc_proc函数(位于kern/process/proc.c中)负责分配并返回一个新的struct proc_struct结构,用于存储新建立的内核线程的管理信息。ucore需要对这个结构进行最基本的初始化,你需要完成这个初始化过程。
【提示】在alloc_proc函数的实现中,需要初始化的proc_struct结构中的成员变量至少包括:state/pid/runs/kstack/need_resched/parent/mm/context/tf/cr3/flags/name。
alloc_proc函数:
static struct proc_struct *
alloc_proc(void) {
struct proc_struct *proc = kmalloc(sizeof(struct proc_struct));
if (proc != NULL) {
//LAB4:EXERCISE1 2013011424
/*
below fields in proc_struct need to be initialized
enum proc_state state; // Process state
int pid; // Process ID
int runs; // the running times of Proces
uintptr_t kstack; // Process kernel stack
volatile bool need_resched; // bool value: need to be rescheduled to release CPU?
struct proc_struct *parent; // the parent process
struct mm_struct *mm; /Process's memory management field
struct context context; // Switch here to run process
struct trapframe *tf; // Trap frame for current interrupt
uintptr_t cr3; // CR3 register: the base addr of Page Directroy Table(PDT)
uint32_t flags; // Process flag
char name[PROC_NAME_LEN + 1]; // Process name
*/
proc->state = PROC_UNINIT;
proc->pid = -1;
proc->runs = 0;
proc->kstack = 0;
proc->need_resched = 0;
proc->parent = NULL;
proc->mm = NULL;
memset(&(proc->context), 0, sizeof(struct context));
proc->tf = NULL;
proc->cr3 = boot_cr3;
proc->flags = 0;
memset(proc->name, 0, PROC_NAME_LEN);
}
return proc;
}
请说明proc_struct中struct context context和struct trapframe *tf成员变量含义和在本实验中的作用是啥?
保护现场用的:
struct trapframe *tf
struct context context
创建一个内核线程需要分配和设置好很多资源。kernel_thread函数通过调用do_fork函数完成具体内核线程的创建工作。do_kernel函数会调用alloc_proc函数来分配并初始化一个进程控制块,但alloc_proc只是找到了一小块内存用以记录进程的必要信息,并没有实际分配这些资源。ucore一般通过do_fork实际创建新的内核线程。do_fork的作用是,创建当前内核线程的一个副本,它们的执行上下文、代码、数据都一样,但是存储位置不同。在这个过程中,需要给新内核线程分配资源,并且复制原进程的状态。你需要完成在kern/process/proc.c中的do_fork函数中的处理过程。它的大致执行步骤包括:
调用alloc_proc,首先获得一块用户信息块。
为进程分配一个内核栈。
复制原进程的内存管理信息到新进程(但内核线程不必做此事)
复制原进程上下文到新进程
将新进程添加到进程列表
唤醒新进程
返回新进程号
int
do_fork(uint32_t clone_flags, uintptr_t stack, struct trapframe *tf) {
int ret = -E_NO_FREE_PROC;
struct proc_struct *proc;
if (nr_process >= MAX_PROCESS) {
goto fork_out;
}
ret = -E_NO_MEM;
//LAB4:EXERCISE2 2013011424
/*
Some Useful MACROs, Functions and DEFINEs, you can use them in below implementation.
MACROs or Functions:
alloc_proc: create a proc struct and init fields (lab4:exercise1)
setup_kstack: alloc pages with size KSTACKPAGE as process kernel stack
copy_mm: process “proc” duplicate OR share process “current“‘s mm according clone_flags
if clone_flags & CLONE_VM, then “share” ; else “duplicate”
copy_thread: setup the trapframe on the process’s kernel stack top and
setup the kernel entry point and stack of process
hash_proc: add proc into proc hash_list
get_pid: alloc a unique pid for process
wakeup_proc: set proc->state = PROC_RUNNABLE
VARIABLES:
proc_list: the process set’s list
nr_process: the number of process set
*/
// 1. call alloc_proc to allocate a proc_struct
// 2. call setup_kstack to allocate a kernel stack for child process
// 3. call copy_mm to dup OR share mm according clone_flag
// 4. call copy_thread to setup tf & context in proc_struct
// 5. insert proc_struct into hash_list && proc_list
// 6. call wakeup_proc to make the new child process RUNNABLE
// 7. set ret vaule using child proc's pid
if ((proc = alloc_proc()) == NULL) {
goto fork_out;
}
proc->parent = current;
if (setup_kstack(proc) != 0) {
goto bad_fork_cleanup_proc;
}
if (copy_mm(clone_flags, proc) != 0) {
goto bad_fork_cleanup_kstack;
}
copy_thread(proc, stack, tf);
bool intr_flag;
local_intr_save(intr_flag);
{
proc->pid = get_pid();
hash_proc(proc);
list_add(&proc_list, &(proc->list_link));
nr_process ++;
}
local_intr_restore(intr_flag);
wakeup_proc(proc);
ret = proc->pid;
fork_out:
return ret;
bad_fork_cleanup_kstack:
put_kstack(proc);
bad_fork_cleanup_proc:
kfree(proc);
goto fork_out;
}
请说明ucore是否做到给每个新fork的线程一个唯一的id?请说明你的分析和理由。
可以做到,每一个进程git_pid得到唯一的一个id.
请在实验报告中简要说明你对proc_run函数的分析。并回答如下问题:
创建了两个内核线程,空闲进程的创建:idleproc proc_init(),创建第一个内核线程:initproc proc_init()。ucore创建的第一个进程通过proc_inti创建 idleproc ,init_proc
执行的函数为init_main。
- 语句local_intr_save(intr_flag);….local_intr_restore(intr_flag);在这里有何作用?请说明理由