北航操作系统实验2019:Lab4-1代码实现参考

部分实现参考自Github前辈们的项目,经过一定程度的勘误。

5月4日 勘误 删除了进程间通信中操作就绪状态链表的内容

5月15日 勘误 加入了sys_ipc_can_send里复制页面的内容

如果这份代码中存在任何问题或错误,请务必不吝在评论区指出。

Exercise 4.1

// user/syscall_wrap.S
LEAF(msyscall)
// TODO: 执行syscall指令,然后从函数返回
syscall
jr ra
nop
END(msyscall)

Exercise 4.2

// lib/syscall.S
NESTED(handle_sys,TF_SIZE, sp)
SAVE_ALL // 用于保存现场的宏
CLI // 关闭全局中断
nop
.set at // 恢复$at寄存器的使用 // TODO: 取出EPC的值,计算一个合理的值(+4)后存回去
lw t1, TF_EPC(sp)
addiu t1, t1, 4
sw t1, TF_EPC(sp) // TODO: 将系统调用号的值存入a0。
// 此处因为本身系统调用号就在a0中,所以什么都不做。 addiu a0, a0, -__SYSCALL_BASE // a0 <- 相对系统调用号
sll t0, a0, 2 // t0 <- 相对系统调用号乘4
la t1, sys_call_table // t1 <- 系统调用表的基地址
addu t1, t1, t0 // t1 <- 特定系统调用的入口
lw t2, 0(t1) // t2 <- 读取特定系统调用的函数入口 lw t0, TF_REG29(sp) // t0 <- 用户栈顶
lw t3, 16(t0) // t3 <- syscall的第5个参数
lw t4, 20(t0) // t4 <- syscall的第6个参数 // TODO: 在当前栈内分配6个参数的空间,并将6个参数复制到合理的位置。
// 六个参数的位置分别是:前4个参数在a0~a3,第5、6个参数在栈内偏移16、20的位置。
//lw a0, TF_REG4(sp) ----- 我本地测试,这行加上之后,第二部分会7/8,不加则8/8
addiu sp, sp, -24
sw t3, 16(sp)
sw t4, 20(sp) jalr t2 // 调用sys_*函数
nop // TODO: 恢复当前的内核栈指针
addiu sp, sp, 24 sw v0, TF_REG2(sp) // 将sys_*函数的返回值存入待恢复现场的v0寄存器 j ret_from_exception // 从异常状态中返回
nop
END(handle_sys)

Exercise 4.3~4.6

// lib/syscall_all.c
void sys_yield(void)
{
struct Trapframe *src = (struct Trapframe *)(KERNEL_SP - sizeof(struct Trapframe));
struct Trapframe *dst = (struct Trapframe *)(TIMESTACK - sizeof(struct Trapframe)); bcopy((void*)src, (void*)dst, sizeof(struct Trapframe));
sched_yield();
} int sys_mem_alloc(int sysno, u_int envid, u_int va, u_int perm)
{
struct Env *env;
struct Page *ppage;
int ret;
ret = 0; if (va >= UTOP || va < 0) {
printf("Error in lib/syscall_all.c, sys_mem_alloc - va illegal\n");
return -E_UNSPECIFIED;
} if ((perm & PTE_COW) || !(perm & PTE_V)) {
printf("Error in lib/syscall_all.c, sys_mem_alloc - perm illegal\n");
return -E_INVAL;
} if (envid2env(envid, &env, 0) < 0) {
printf("Error in lib/syscall_all.c, sys_mem_alloc - envid illegal\n");
return -E_BAD_ENV;
} if (page_alloc(&ppage) < 0) {
printf("Error in lib/syscall_all.c, sys_mem_alloc - memory insufficient\n");
return -E_NO_MEM;
} if (page_insert(env->env_pgdir, ppage, va, perm) < 0) {
printf("Error in lib/syscall_all.c, sys_mem_alloc - pgdir insert failed\n");
return -E_NO_MEM;
} return 0;
} int sys_mem_map(int sysno, u_int srcid, u_int srcva, u_int dstid, u_int dstva, u_int perm)
{
int ret;
u_int round_srcva, round_dstva;
struct Env *srcenv;
struct Env *dstenv;
struct Page *ppage;
Pte *ppte; ppage = NULL;
ret = 0;
round_srcva = ROUNDDOWN(srcva, BY2PG);
round_dstva = ROUNDDOWN(dstva, BY2PG); if (srcva >= UTOP || dstva >= UTOP || srcva < 0 || dstva < 0) {
printf("Error in lib/syscall_all.c, sys_mem_map - va illegal\n");
return -E_UNSPECIFIED;
} if (!(perm & PTE_V)) {
printf("Error in lib/syscall_all.c, sys_mem_map - perm illegal\n");
return -E_INVAL;
} if (envid2env(srcid, &srcenv, 0) < 0) {
printf("Error in lib/syscall_all.c, sys_mem_map - srcid illegal\n");
return -E_BAD_ENV;
} if (envid2env(dstid, &dstenv, 0) < 0) {
printf("Error in lib/syscall_all.c, sys_mem_map - dstid illegal\n");
return -E_BAD_ENV;
} if ((ppage = page_lookup(srcenv -> env_pgdir, round_srcva, &ppte)) == 0) {
printf("Error in lib/syscall_all.c, sys_mem_map - pgdir insert failed\n");
return -E_UNSPECIFIED;
} if (page_insert(dstenv -> env_pgdir, ppage, round_dstva, perm) < 0) {
printf("Error in lib/syscall_all.c, sys_mem_map - dstid illegal\n");
return -E_NO_MEM;
} return ret;
} int sys_mem_unmap(int sysno, u_int envid, u_int va)
{
int ret = 0;
struct Env *env; if (va >= UTOP || va < 0) {
printf("Error in lib/syscall_all.c, sys_mem_unmap - va illegal\n");
return -E_INVAL;
} if (envid2env(envid, &env, PTE_V) < 0) {
printf("Error in lib/syscall_all.c, sys_mem_unmap - envid illegal\n");
return -E_INVAL;
} page_remove(env -> env_pgdir, va); return ret;
}

Exercise 4.7

// lib/syscall_all.c
void sys_ipc_recv(int sysno, u_int dstva)
{
if (dstva >= UTOP) {
return;
}
curenv -> env_ipc_recving = 1;
curenv -> env_ipc_dstva = dstva;
curenv -> env_status = ENV_NOT_RUNNABLE;
sys_yield();
} int sys_ipc_can_send(int sysno, u_int envid, u_int value, u_int srcva, u_int perm)
{ int r;
struct Env *e;
struct Page *p;
Pte *ppte; if (srcva >= UTOP || srcva < 0) {
return -E_INVAL;
} if (envid2env(envid, &e, 0) < 0) {
return -E_INVAL;
} if (e -> env_ipc_recving == 0) {
return -E_IPC_NOT_RECV;
} if (srcva != 0) {
e -> env_ipc_perm = perm|PTE_V|PTE_R;
if((p=page_lookup(curenv->env_pgdir,srcva,0))<=0){
return -E_INVAL;
}else if(page_insert(e->env_pgdir,p,e->env_ipc_dstva,perm)<0){
printf("dst pot failed.\n");
return -E_INVAL;
}
}
e -> env_ipc_recving = 0;
e -> env_status = ENV_RUNNABLE;
e -> env_ipc_value = value;
e -> env_ipc_from = curenv -> env_id; return 0;
}

一并需要修改的地方

// Lab3: lib/sched.c
void sched_yield(void)
{
static struct Env *cur = NULL;
static u_int curtime = 0;
static int x = 0;
while (curtime <= 0 || cur && cur -> env_status != ENV_RUNNABLE) {
if (cur != NULL) {
LIST_REMOVE(cur, env_sched_link);
LIST_INSERT_HEAD(&env_sched_list[1-x], cur, env_sched_link);
}
while ((LIST_FIRST(&env_sched_list[x])) == NULL) {
x = 1 - x;
}
cur = LIST_FIRST(&env_sched_list[x]);
curtime = cur -> env_pri;
}
curtime--;
env_run(cur);
}

北航操作系统实验2019:Lab4-1代码实现参考的更多相关文章

  1. 北航操作系统实验2019:Lab4-1流程梳理

    北航操作系统实验2019:Lab4-1流程梳理 前言 操作系统的实验课实在令人头秃.我们需要在两周时间内学习相关知识.读懂指导书.读懂代码.补全代码.处理玄学bug和祖传bug,以及回答令人窒息的思考 ...

  2. [操作系统实验lab3]实验报告

    [感受] 这次操作系统实验感觉还是比较难的,除了因为助教老师笔误引发的2个错误外,还有一些关键性的理解的地方感觉还没有很到位,这些天一直在不断地消化.理解Lab3里的内容,到现在感觉比Lab2里面所蕴 ...

  3. sdut oj 操作系统实验--SSTF磁盘调度算法【操作系统算法】

    操作系统实验--SSTF磁盘调度算法 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 磁盘调度在多道程序设计的计算机系统中,各个进 ...

  4. Lab_0操作系统实验准备(全)

    一.实验介绍 实验目的: 知识储备: 二.相关下载 1.下载镜像文件 这个镜像文件是vdi类型的,只能用visualbox下载 链接:https://pan.baidu.com/s/1L7WX6ju4 ...

  5. 操作系统实验(一)-Shell编程

    操作系统实验:Shell编程 emmmmm,实验前老师发了一份实验说明,里面有教怎么配置虚拟机Ubuntu.这里就不做过多叙述,需要说明的是,kali和ubuntu都可以以shell运行这个C语言程序 ...

  6. 操作系统实验一:进程管理(含成功运行C语言源代码)

    目录 操作系统实验一:进程管理 1.实验目的 2.实验内容 3.实验准备 3.1.1进程的含义 3.1.2进程的状态 3.1.3进程状态之间的转换 3.2 进程控制块PCB 3.2.1进程控制块的作用 ...

  7. [No00003D]操作系统Operating Systems信号量的代码实现Coding Semaphore &死锁处理Deadlock

    操作系统Operating Systems信号量的代码实现Coding Semaphore &死锁处理Deadlock 可以操刀了—从纸上到实际 从Linux 0.11 那里学点东西… 读磁盘 ...

  8. [Java] 实验5參考代码

    实验4月3日晚截止,实验截止后将在此给出完整的參考代码. 1. 怎样使用以下的代码模板: 1.1 在eclipse中创建相应名称的类     1.2 将代码拷贝到类文件中 1.3 在//todo凝视中 ...

  9. [Java] 实验6參考代码

    1. 大家的.java程序都须要在一个"缺省包"(default package)下编写\执行\提交,不要去命名新的package     - 系统不支持package contr ...

随机推荐

  1. FireFox add dict

    1.Firefox add add-ons: inline translation 2.https://login.live.com/login.srf?wa=wsignin1.0&wtrea ...

  2. Git----时光穿梭机之工作区和暂存区03

    Git和其他版本控制系统SVN的一个不同之处就是有暂存区的概念 先来看看名词解释 工作区(Working Directory) 就是你在我电脑里能看到的目录,比如我的learngittest文件夹就是 ...

  3. 使用通配符配置action

    建立struts2wildcard项目,此实例基本仿照前面前面第7点的实例改写而成.为了使用通配符,只需要改写配置文件即可.此实例未使用通配时的配置文件如下: <action name=&quo ...

  4. iOS对HTTPS证书链的验证原理

    今天看到所在的某个开发群问https原理,之前做HTTPS ,下面简单说下原理.希望能帮助你理解. HTTPS从最终的数据解析的角度,与HTTP相同.HTTPS将HTTP协议数据包放到SSL/TSL层 ...

  5. 磁盘512n,512e,4k原生磁盘的区别和操作系统支持

    磁盘按照物理扇区大小的不同分为三种512byte原生扇区硬盘(512n),4KB扇区仿真512byte(512E)磁盘,4kB扇区原生磁盘. 首先说物理扇区,扇区是硬盘上最小的读写单位,这个是硬盘决定 ...

  6. Qt的安装和使用中的常见问题(简略版)

    对于喜欢研究细节的朋友,可参考Qt的安装和使用中的常见问题(详细版). 目录 1.引入 2.Qt简介 3.Qt版本 3.1 查看安装的Qt版本 3.2 查看当前项目使用的Qt版本 3.3 查看当前项目 ...

  7. 前端基础之:JQuery

  8. 职责链模式c#(处理车)

    using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace 职责链模式{  ...

  9. win7下面iis错误汇总

    1.分析器错误消息: 无法识别的属性“targetFramework”.请注意属性名称区分大小写 解决方法: 修改.NET Framework 版本为相应版本即可,我以前用的是2.0换成4.0的时候出 ...

  10. 各大主流.Net的IOC框架性能测试比较(转)

    出处:http://www.cnblogs.com/liping13599168/archive/2011/07/17/2108734.html 在上一篇中,我简单介绍了下Autofac的使用,有人希 ...