process&thread

Exercise 2:创建并且运行process

首先是env_init()函数

函数的作用:1. 初始化所有的在envs数组中的 Env结构体,并把它们加入到 env_free_list中。

  1. 还要调用 env_init_percpu,这个函数要配置段式内存管理系统,让它所管理的段,可能具有两种访问优

    先级其中的一种,一个是内核运行时的0优先级,以及用户运行时的3优先级

code如下:

void
env_init(void)
{
	// Set up envs array
	// LAB 3: Your code here.
	int number;
	env_free_list = NULL;
	for ( number = NENV - 1; number > 0 ; number--) //the maxium number of the free_list
	{
		envs[i].env_id = 0;
		envs[i].env_status = ENV_FREE;
		envs[i].env_link = env_free_list; //the env_free_list is a pointer which point to the next free process
		env_free_list = &envs[i];//update the env_free_list
	}
	// panic("env_init not yet implemented");
	// Per-CPU part of the initialization
	env_init_percpu();
}

之后是env_setup_vm()函数:

具体作用:为一个新的process分配一个页面目录,并且初始化这个页面目录中与kernal相关的部分

code:

static int
env_setup_vm(struct Env *e)
{
	int i;
	struct PageInfo *p = NULL;

	// Allocate a page for the page directory
	if (!(p = page_alloc(ALLOC_ZERO)))
		return -E_NO_MEM;
		
	// LAB 3: Your code here.
	e->env_pgdir = (pde_t*)page2kva(p);
	p->pp_ref++; 
	//put the directory below UTOP
	for (i = 0; i < PDX(UTOP); i++)
	{
		e->env_pgdir[i] = 0;
	}
	//put the directory above UTOP
	for ( i = PDX(UTOP) ; i < NPDENTRIES; i++)
	{
		e->env_pgdir[i] = kern_pgdir[i];
	}
	// e->env_pgdir = KADDR(page2pa(p));
	// memcpy((void*)(e->env_pgdir), (void*)kern_pgdir, PGSIZE);

	// UVPT maps the env's own page table read-only.
	// Permissions: kernel R, user R
	e->env_pgdir[PDX(UVPT)] = PADDR(e->env_pgdir) | PTE_P | PTE_U;

	return 0;
}

region_alloc()函数

作用:为process分配和映射物理内存

Hint:当”len“个bytes和对应虚拟地址为”va“不是页对齐的时候会更加简单,va向下取整,而va+len向上取整

code

static void
region_alloc(struct Env *e, void *va, size_t len)
{
	// LAB 3: Your code here.
	// (But only if you need it for load_icode.)
	//
	// Hint: It is easier to use region_alloc if the caller can pass
	//   'va' and 'len' values that are not page-aligned.
	//   You should round va down, and round (va + len) up.
	//   (Watch out for corner-cases!)

	uint32_t VA = ROUNDDOWN((uint32_t)va, PGSIZE);
	uint32_t N = ROUNDUP((uint32_t)va + len, PGSIZE);

	for(uint32_t i = VA; i< N; i += PGSIZE){
		if(page_lookup(e->env_pgdir, (void*)i, NULL))
			continue;
		struct PageInfo* pp = page_alloc(0);
		if(!pp) 
			panic("region_alloc: alloc env region failed.");
		page_insert(e->env_pgdir, pp, (void*)i, PTE_U|PTE_W);
	}
}

load_icode()函数

主要作用:解析二进制ELF映像,并且把它的内容加到对应的process的用户地址空间中

code

static void
load_icode(struct Env *e, uint8_t *binary)
{
	// LAB 3: Your code here.
	struct Elf *elf = (struct Elf*) binary;
	struct Proghdr* ph, *eph;

	if (elf->e_magic != ELF_MAGIC)
		panic("Not valid ELF file.");

	ph = (struct Proghdr *) ((uint8_t *) elf + elf->e_phoff);
		
	eph = ph + elf->e_phnum;
	
	lcr3(PADDR(e->env_pgdir));
	for (; ph < eph; ph++){
		if(!(ph->p_filesz <= ph->p_memsz))
			panic("Bad proghdr!");
			
		if(ph->p_type != ELF_PROG_LOAD) 
			continue;
		uint32_t va = ph->p_va;
	
		region_alloc(e, (void*)va,  ph->p_memsz);
		memcpy((void*)va, (void*)(binary + ph->p_offset), ph->p_memsz);
		memset((void*)va+ph->p_filesz, '\0', ph->p_memsz - ph->p_filesz);
	}

	// switch back to kern_pgdir
	lcr3(PADDR(kern_pgdir));
	
	// save the eip in trapframe
	e->env_tf.tf_eip = elf->e_entry;

	// Now map one page for the program's initial stack
	// at virtual address USTACKTOP - PGSIZE.

	// LAB 3: Your code here.
	region_alloc(e, (void*)(USTACKTOP - PGSIZE), PGSIZE);
	// note that stack top has been set by env_alloc()
}

env_creat()函数:

参数* binary:将要加载的可执行文件的起始位置,type:process类型

code:

void
env_create(uint8_t *binary, enum EnvType type)
{
	// LAB 3: Your code here.
	// panic("env_create not yet implemented");
	struct Env* e;
	int r;
	if ((r = env_alloc(&e, 0) != 0)) {
		panic("create env failed\n");
	}
	load_icode(e, binary);
	e->env_type = type;
}

env_run()

void
env_run(struct Env *e)
{
	if (curenv != NULL && curenv->env_status == ENV_RUNNING) {
		curenv->env_status = ENV_RUNNABLE;
	}
	curenv = e;
	e->env_status = ENV_RUNNING;
	e->env_runs++;
	lcr3(PADDR(e->env_pgdir));   
	env_pop_tf(&e->env_tf);
	// LAB 3: Your code here.

	panic("env_run not yet implemented");
}

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

TLS实验 上一篇
IP/ICMP Attack lab 下一篇