ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2019-04-29 20:50:27  阅读:368  来源: 互联网

标签:return lib int 北航 sys syscall 2019 env Lab4


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

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

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

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;
        LIST_REMOVE(curenv, env_sched_link);  // Lab4可有可无
        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;
        }
        e -> env_ipc_recving = 0;
        e -> env_status = ENV_RUNNABLE;
        LIST_INSERT_HEAD(&env_sched_list[0], e, env_sched_link);  // Lab4可有可无
        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);
}

标签:return,lib,int,北航,sys,syscall,2019,env,Lab4
来源: https://www.cnblogs.com/sharinka0715/p/10792755.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有