北航操作系统实验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. 用JDK自带的包来解析XML文件(DOM+xpath)

    DOM编程不要其它的依赖包,因为JDK里自带的JDK里含有的上面提到的org.w3c.dom.org.xml.sax 和javax.xml.parsers包就可以满意条件了.(1)org.w3c.do ...

  2. docker-compose搭建单机多节点es + kibana

    docker-compose.yml配置如下: version: '2.2' services: elasticsearch: image: docker.elastic.co/elasticsear ...

  3. selenium+java,实现部分截图功能,-针对单个元素的截图

    有时候需要元素的截图,不需要整个截图.整理一个针对元素的截图的方法. 创建一个Java类,实现截取元素的方法 package com.lozz.utils; import java.awt.Recta ...

  4. FP变更物料编码(增加尾缀)

    FP物料编码增加尾缀的程序,标准物料编码是18位,目前程序中增加尾缀的有三种1.DUMMY 2.SP开头 3.P开头 4.C开头 5.BP对应处理程序如下:1.DUMMY       SAP_MATE ...

  5. jekins测试环境自动化

    最近搭建测试环境自动化,之前都是用机器猫.机器猫的流程大概是这样,开发打包上传到svn,给测试一个svn地址,测试到机器猫上传文件,然后再运行启动. 为了减去开发打包这个环节,所以专用jenkins. ...

  6. ios 获取当前wifi名称

    ios5之前可以通过读取配置文件获取,ios5以后苹果修改wifi列表文件位置,只有root权限才可以读取. ios4:/System/Library/SystemConfiguration/WiFi ...

  7. USB相关注册表

    计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{ SYSTEM\\CurrentControlSet\\Control\\ ...

  8. Web数据挖掘综述

     

  9. swoole WebSocket 消息推送

    server.php <?php //连接本地的 Redis 服务 $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $r ...

  10. 4D(DLG,DRG,DOM,DEM)

    基于“倾斜+LiDAR+车载”的实景三维建模实现:链接 MapGIS数据可不可以做到数据融合 遥感影像