代码改变世界

[JOS笔记]Lab3--env分析

2009-02-12 22:31  hyddd  阅读(1864)  评论(0编辑  收藏  举报

  在JOS里面,它用“environment”(环境)去代替"process"(进程)这一概念,我的理解是:你大概可以认为,一个进程对应一个env结构体,切换进程即是切换env。

  下面我们来看一下Env结构体:

/*
 *  inc/env.h里,定义了Env结构体
 */
struct
 Env {
        
struct Trapframe env_tf;        // Saved registers
        LIST_ENTRY(Env) env_link;       // Free list link pointers
        u_int env_id;                   // Unique environment identifier
        u_int env_parent_id;            // env_id of this env's parent
        u_int env_status;               // Status of the environment
                                                                                
        
// Address space
        pde_t *env_pgdir;                // Kernel virtual address of page dir  ("typedef uint32_t pde_t")
        u_int env_cr3;                  // Physical address of page dir
};

 

从上面看到,Env包含下面几个部分:

1.struct Trapframe env_tf:env_tf是一个Trapframe结构,下面首先看看Trapframe结构体:

/*
 * inc/trap.h里面,有Trapfame的定义
 */

struct Trapframe {
    
struct PushRegs tf_regs;
    uint16_t tf_es;
    uint16_t tf_padding1;
    uint16_t tf_ds;
    uint16_t tf_padding2;
    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_padding3;
    uint32_t tf_eflags;
    
/* below here only when crossing rings, such as from user to kernel */
    uintptr_t tf_esp;
    uint16_t tf_ss;
    uint16_t tf_padding4;
};

struct PushRegs {
    /* registers as pushed by pusha */
    uint32_t reg_edi;
    uint32_t reg_esi;
    uint32_t reg_ebp;
    uint32_t reg_oesp;        /* Useless */
    uint32_t reg_ebx;
    uint32_t reg_edx;
    uint32_t reg_ecx;
    uint32_t reg_eax;
};

Trapframe用于存储各种寄存器的值,因为切换进程时,我们需要保护进程现场,所谓现场,可以粗略地认为就是各种存储器的值。

 

2. LIST_ENTRY(Env) env_link:先看看LIST_ENTRY的结构:

/*
 * inc/queue.h
 *
 * Use this inside a structure "LIST_ENTRY(type) field" to use
 * x as the list piece.
 *
 * The le_prev points at the pointer to the structure containing
 * this very LIST_ENTRY, so that if we want to remove this list entry,
 * we can do *le_prev = le_next to update the structure pointing at us.
 
*/
#define    LIST_ENTRY(type)                        \
struct {                                \
    
struct type *le_next;    /* next element */            \
    
struct type **le_prev;    /* ptr to ptr to this element */    \
}
嗯~很好,说明说得很清楚,那么现在可以看出env_link是一个env的链表,至于作用是什么先放一下。

3.env_id:env在env数组里的唯一标识。

4.env_parent_id:创建这个env的env的env_id(很绕口-_-),通过它你可以还原整个进程的创建族谱。

5.env_status:标记这个env的状态,它的值见下面代码:

// Values of env_status in struct Env
#define ENV_FREE        0        //表明这个env是inactive的,这时它将会存储在env_free_list
#define ENV_RUNNABLE        1     //表明这个是一个active的env,正等待运行!
#define ENV_NOT_RUNNABLE    2    //也是一个active的env,但是现在还不能运行,因为它正在等待另一个进程的通信

6.env_pgdir:pgdir很熟悉的字眼,它是指向env页目录的虚拟地址指针

7.env_cr3:存储本env对应的pgdir的物理首地址

 

OK~现在我们在来看一下kern/env.c

struct Env *envs = NULL;        // All environments
struct Env *curenv = NULL;            // The current env
static struct Env_list env_free_list;    // Free list

这样一看,又清晰了很多了,这个对应了刚才上面所说的env_status的3种状态。