ucore lab4

Lab4 内核线程管理

[TOC]

练习0:填写已有实验

本实验依赖实验1/2/3。请把你做的实验1/2/3的代码填入本实验中代码中有“LAB1”,“LAB2”,“LAB3”的注释相应部分。

练习1:分配并初始化一个进程控制块

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

练习2:为新创建的内核线程分配资源

创建一个内核线程需要分配和设置好很多资源。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.

练习3:阅读代码,理解 proc_run 函数和它调用的函数如何完成进程切换的。

请在实验报告中简要说明你对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);在这里有何作用?请说明理由

实验截图

实验截图

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝鲸123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值