ucore lab4

原创 2016年04月25日 19:57:28

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);在这里有何作用?请说明理由

实验截图

实验截图

版权声明:本文为博主原创文章,未经博主允许不得转载。

ucore操作系统实验lab4 -- 内核线程管理

练习一:分配并初始化一个进程控制块(需要编码)   alloc_proc函数(位于kern/process/proc.c中)负责分配并返回一个新的struct proc_struct结构,用于存储新建...

操作系统ucore lab4实验报告

操作系统lab4实验报告

操作系统ucore lab4

操作系统ucore lab4 一练习0 二练习1 1 内核线程 2 进程控制块 3 代码实现 三练习2 1 创建第0个内核线程idleproc 2 创建第1个内核线程initproc 四练习3 操作系...
  • Aslani
  • Aslani
  • 2017年04月30日 15:51
  • 53

ucore操作系统lab4实验报告(理论部分)

内核线程管理 一、关键数据结构 -- 进程控制块 1、首先简单说明一下内核线程与用户进程的区别: 内核线程只运行在内核态。用户进程会在在用户态和内核态交替运行所有内核线程共用ucore内核内存空间,不...

ucore lab实验总结(代码+报告)

  • 2017年08月02日 09:38
  • 12.65MB
  • 下载

操作系统ucore lab5实验报告

操作系统lab5实验报告

操作系统ucore lab8实验报告

操作系统lab8实验报告

ucore操作系统lab2实验报告

练习1:实现 first-fit 连续物理内存分配算法 在实现first fit 内存分配算法的回收函数时,要考虑地址连续的空闲块之间的合并操作。提示:在建立空闲页块链表时,需要按照空闲页块起始地址来...

ucore-lab1实验报告

练习一: 1、操作系统镜像文件ucore.img是如何一步一步生成的?(需要比较详细地解释Makefile中每一条相关命令和命令参数的含义,以及说明命令导致的结果) + cc kern/init/i...

# 操作系统实验报告:ucore-lab1

参考链接: 1. GDB 常用命令参考手册 2. 一篇优秀的gdb的总结 3. lab1实验报告 4. 清华大学操作系统实验lab1实验报告 5. e...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ucore lab4
举报原因:
原因补充:

(最多只允许输入30个字)