操作系统实验四实验报告

本文是关于操作系统实验的报告,主要涉及内核线程的管理和进程切换。实验内容包括分配并初始化进程控制块,为新创建的内核线程分配资源,以及理解proc_run函数及其在进程切换中的作用。通过分析代码,解释了如何创建内核线程,设置中断帧和上下文,并详细阐述了proc_run函数如何进行进程调度和切换。
摘要由CSDN通过智能技术生成

实验四:内核线程管理


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

首先来看几个比较重要的数据结构,kern/process/proc.h中定义的进程控制块及kern/trap/trap.h中定义的中断帧

struct proc_struct {
    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
    list_entry_t list_link;                     // Process link list 
    list_entry_t hash_link;                     // Process hash list
}

struct trapframe {
    /* below here is a struct of general registers and defined by software */
    // 当中断异常发生时,此处结构内的通用寄存器信息由软件负责压栈保存
    struct pushregs tf_regs;                    
    /* below here are segement registers and defined by software */
    // 当中断异常发生时,此处的段寄存器信息由软件负责压栈保存
    uint16_t tf_gs;
    uint16_t tf_padding0;
    uint16_t tf_fs;
    uint16_t tf_padding1;
    uint16_t tf_es;                             
    uint16_t tf_padding2;
    uint16_t tf_ds;
    uint16_t tf_padding3;
    uint32_t tf_trapno;
    /* below here defined by x86 hardware */
    // 当中断异常发生时,此处的信息由硬件压栈保存
    uint32_t tf_err;
    uintptr_t tf_eip;
    uint16_t tf_cs;                             
    uint16_t tf_padding4;
    uint32_t tf_eflags;
    /* below here only when crossing rings, such as from user to kernel, defined by hardware */
    // 仅发生特权级改变时,此处额外的信息由硬件压栈保存
    uintptr_t tf_esp;
    uint16_t tf_ss;                             
    uint16_t tf_padding5;
}

struct context {
    uint32_t eip;
    uint32_t esp;
    uint32_t ebx;
    uint32_t ecx;
    uint32_t edx;
    uint32_t esi;
    uint32_t edi;
    uint32_t ebp;
}

这里可以看到struct contextstruct trapframe中有很多寄存器是一样的,前者用于进程上下文切换,后者用于中断上下文切换。注意这两者的含义是不一样的,在本实验中一个进程开始执行需要系统进行初始化,此时tf被用来保存中断帧,而进程执行时是通过context来完成切换的,详细见练习3的说明。

结构中一些重要的成员变量说明如下

  • mm内存管理信息,包括内存映射列表、页表指针等
  • state进程所处的状态,有PROC_UNINITPROC_SLEEPINGPROC_RUNNABLEPROC_ZOMBIE四种,定义在enum proc_state
  • parent父进程,在所有进程中只有内核创建的第一个内核线程idleproc没有父进程,内核根据父子关系建立树形结构维护一些特殊的操作
  • context进程的上下文,保存寄存器,用于进程切换
  • tf中断帧,总是指向内核栈的某个位置,当进程发生中断异常,从用户跳到内核时,中断帧记录了进程在中断前的状态,由于允许中断嵌套,因此ucore在内核栈上维护了tf链,保证tf总是能够指向当前的trapframe
  • kstack每个线程都有内核栈,并且位于内核地址空间的不同位置,对于内核线程,该栈就是运行时程序使用的栈,对于普通进程,该栈就是发生特权级改变时需保存被打断硬件信息的栈

另外为了管理系统中所有的进程控制块,ucore维护了一些重要的全局变量

  • static struct proc *current当前占用处理机并处于运行状态的进程控制块指针
  • static list_entry_t hash_list[HASH_LIST_SIZE]所有进程控制块的哈希表,hash_link将基于pid链接入这个哈希表

根据实验手册及代码的提示,练习1的代码如下

把proc进行初步初始化(即把proc_struct中的各个成员变量清零)。但有些成员变量设置了特殊的值

// alloc_proc - alloc a proc_struct and init all fields of proc_struct
static struct proc_struct *
alloc_proc(void) {
    struct proc_struct *proc = kmalloc(sizeof(struct proc_struct));
    if (proc != NULL) {
        proc->state = PROC_UNINIT;                 // 设置进程为初始态
        proc->pid = -
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值