mit 6.828 lab4-抢占式多任务

partA

实现unix-like的fork(),允许用户进程去创建它自己的拷贝。
sys_exfork(void),传入父进程id使用env_alloc从空闲进程列表中分配一个Env,在env_alloc里面设置了env_pgdir
1.将父进程的env_tf复制给新的进程的env_tf;
2.设置进程状态图为ENV_NOT_RUNNABLE;
3,将存放返回值的寄存器值设置为0;
return 当前分配的进程id;

sys_exofork之后其实子进程的env_pgdir里面的内容这个时候都是空的,父进程拷贝自己的地址空间给子进程在fork()调用一些系统调用中实现。

static envid_t
sys_exofork(void)
{
	// Create the new environment with env_alloc(), from kern/env.c.
	// It should be left as env_alloc created it, except that
	// status is set to ENV_NOT_RUNNABLE, and the register set is copied
	// from the current environment -- but tweaked so sys_exofork
	// will appear to return 0.

	// LAB 4: Your code here.
	struct Env*e;
	int ret=env_alloc(&e,curenv->env_id);
	if(ret<0){
		return ret;
	} 
	e->env_tf=curenv->env_tf;
	e->env_status=ENV_NOT_RUNNABLE;
	e->env_tf.tf_regs.reg_eax=0;
	return e->env_id;
}

sys_env_set_status(),设置指定环境的状态为ENV_RUNNABLE或ENV_NOT_RUNNABLE。
根据envid获取Env,设置Env中的status

static int
sys_env_set_status(envid_t envid, int status)
{
	// Hint: Use the 'envid2env' function from kern/env.c to translate an
	// envid to a struct Env.
	// You should set envid2env's third argument to 1, which will
	// check whether the current environment has permission to set
	// envid's status.

	// LAB 4: Your code here.
	if(status!=ENV_NOT_RUNNABLE&&status!=ENV_RUNNABLE)
	return -E_INVAL;
	
	struct Env*e;
	int ret=envid2env(envid,&e,1);
	if(ret<0){
		return ret;
	}
	e->env_status=status;
	return 0;
}

sys_page_alloc,分配一页物理内存,并将其映射到给定进程地址空间中的给定虚拟地址。
注意va必须要是一个页对齐的虚拟地址。

// Allocate a page of memory and map it at 'va' with permission
// 'perm' in the address space of 'envid'.
// The page's contents are set to 0.
// If a page is already mapped at 'va', that page is unmapped as a
// side effect.
//
// perm -- PTE_U | PTE_P must be set, PTE_AVAIL | PTE_W may or may not be set,
//         but no other bits may be set.  See PTE_SYSCALL in inc/mmu.h.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
//	-E_INVAL if va >= UTOP, or va is not page-aligned.
//	-E_INVAL if perm is inappropriate (see above).
//	-E_NO_MEM if there's no memory to allocate the new page,
//		or to allocate any necessary page tables.
static int
sys_page_alloc(envid_t envid, void *va, int perm)
{
	// Hint: This function is a wrapper around page_alloc() and
	//   page_insert() from kern/pmap.c.
	//   Most of the new code you write should be to check the
	//   parameters for correctness.
	//   If page_insert() fails, remember to free the page you
	//   allocated!

	// LAB 4: Your code here.
	struct Env*e;
	int ret=envid2env(envid,&e,1);
	if(ret) return -E_BAD_ENV;

	if((va>=(void*)UTOP)||(ROUNDDOWN(va,PGSIZE)!=va)) return -E_INVAL;

	int flag=PTE_U|PTE_P;
	if((perm&flag)!=flag) return -E_INVAL;

	struct PageInfo*pg=page_alloc(1);
	if(!pg) return -E_NO_MEM;

	ret=page_insert(e->env_pgdir,pg,va,perm); //建立映射,就是修改目录和页表
	if(ret){
		page_free(pg);
		return ret;
	}
	return 0;
}

sys_page_map(),复制一个页映射(not the contents of a page!!)from 一个进程的地址空间到另外一个,保留内存共享安排,以便新映射和旧映射都引用物理内存的同一页。

// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.
	struct Env*se,*de;
	int ret=envid2env(srcenvid,&se,1);
	if(ret) return ret;
	ret=envid2env(dstenvid,&de,1);
	if(ret) return ret;

	if((srcva>=(void*)UTOP)||(dstva>=(void*)UTOP)||
	(ROUNDDOWN(srcva,PGSIZE)!=srcva)||(ROUNDDOWN(dstva,PGSIZE)!=dstva))
	return -E_INVAL;

	pte_t *pte;
	struct PageInfo*pg=page_lookup(se->env_pgdir,srcva,&pte);
	if(!pg) return -E_INVAL;

	int flag=PTE_U|PTE_P;
	if((perm&flag)!=flag) return -E_INVAL;

	if(((*pte&PTE_W)==0)&&(perm&PTE_W))	return -E_INVAL;

	ret=page_insert(de->env_pgdir,pg,dstva,perm);
	if(ret<0)
	return -E_NO_MEM;
	return 0;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值