北航操作系统实验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. java 序列化时排除指定属性

    java 序列化对象如何排除指定属性呢? java 中序列化对象有多种方式:struts2 ,jackson,json-lib (1)使用struts2 json插件 依赖的jar包:struts2- ...

  2. 130. Surrounded Regions (Graph; DFS)

    Given a 2D board containing 'X' and 'O', capture all regions surrounded by 'X'. A region is captured ...

  3. 101. Symmetric Tree (Tree, Queue; DFS, WFS)

    Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center). For e ...

  4. ios 解决Wkwebview闪烁问题

    // 网页闪烁问题    if ([self.webView.realWebView isKindOfClass:[WKWebView class]]) {         ((WKWebView * ...

  5. eclipse或tomcat web项目启动失败其中一种解决办法

    失败信息如下: java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to s ...

  6. php从数组中取出一段 之 array_slice

    array array_slice ( array $array , int $offset [, int $length [, bool $preserve_keys ]] ) array_slic ...

  7. MySQL数据库远程连接的配置方案

    首先,目的是使用本机可视化工具SQLyog通过IP地址远程访问另一台机器上的MySQL数据库. 本人实践的MySQL版本是MySQL 5.7.23,数据库部署的主机系统是Windows.这些简单配置均 ...

  8. Python爬虫利器六之PyQuery的用法

    前言 你是否觉得 XPath 的用法多少有点晦涩难记呢? 你是否觉得 BeautifulSoup 的语法多少有些悭吝难懂呢? 你是否甚至还在苦苦研究正则表达式却因为少些了一个点而抓狂呢? 你是否已经有 ...

  9. [OS]windows 2012 server-Local users and groups-Backup Operators

    怎样找到windows 2012 server上的Backup Operators Press the Windows + R keys to open the Run dialog, type lu ...

  10. SpringCloud之服务注册-eureka

    类似于DUBBO 的zookeeper, SpringCloud本身提供一套服务注册中心--eureka 与zookeeper的区别在于 1:zookeeper本身就是一个应用,安装即可用:eurek ...