北航操作系统实验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. Eclipse can not find the tag library descriptor for http://java.sun.com/jsf/*

    问题页面: <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%> <%@ ta ...

  2. LUA中相同签名函数覆盖

    function test() print('test')end function test() print('test22222')end test() --输出test2222

  3. 创建maven版的java工程

    步骤如下: 1.第一步 2.第二步: 3.第三步:

  4. Linux 入侵检测

    一.检查系统日志 检查系统错误登陆日志,统计IP重试次数 # 这里使用了lastb命令,该命令需要root权限,可以显示所有登陆信息.这里仅仅显示的root用户的,读者可以更具实际情况自行确定,或者直 ...

  5. Matlab中插值函数汇总(下)

    Matlab中插值函数汇总分上下两个部分,主要整合自matlabsky论坛dynamic发表于2009-2-21 21:53:26 的主题帖,以及豆丁网rickoon上传的教材第8章<插值,拟合 ...

  6. 查看linux中某个端口(port)是否被占用

    1.使用lsof lsof -i:端口号                     查看某个端口是否被占用 2.使用netstat 使用netstat -anp|grep 80

  7. Ice_cream’s world II(最小树形图,加虚点)

    Ice_cream’s world II http://acm.hdu.edu.cn/showproblem.php?pid=2121 Time Limit: 3000/1000 MS (Java/O ...

  8. 784. Letter Case Permutation 字符串中字母的大小写组合

    [抄题]: Given a string S, we can transform every letter individually to be lowercase or uppercase to c ...

  9. 在线编辑器CKeditor,CKfinder

    在线编辑器的分类: 常见的在线编辑器有很多,比较常用的有FCKeditor(在线编辑器——Ajax 浏览器 端服务器文件管理器),CKeditor(在线编辑器与服务器端文件管理器的分离,) 其中CKe ...

  10. [Selenium]重写拖拽dragWidgetToElementContainner()

    public void dragWidgetToElementContainner(String widgetName, String targetPosition){ WebElement widg ...