首页 > 其他分享 >Xv6 Lab2

Xv6 Lab2

时间:2023-07-13 19:22:33浏览次数:52  
标签:SYS trace mask Xv6 sys Lab2 num proc

系统调用

Lab1 主要是基于提供的系统调用接口来编写一些小工具程序,而 Lab2 则是要我们自己实现系统调用,并提供系统调用的接口。

以本次 Lab 要我们实现的 trace 调用为例,说明一下系统调用的流程:

user/trace.c 的第 $15$ 行,调用了属于 system call 的 trace 函数,当前执行 make qemu 是无法成功的,因为我们还没有给用户提供接口。因此,我们需要在 user/user.h 里面添加系统调用 trace 的函数声明(prototype)。

我们需要在 user/usys.pl 中追加 entry("trace"); 这一行,从而添加一个 trap entry,从而实现调用 trace 时会发生 trap,从而会执行 ECALL 指令,并且会将系统调用的接口的参数(这里就是 trace 的参数)的存入寄存器 a0a1 等(从左往右第一个参数的地址存入 a0,依次类推),此外,还会将 trace 对应的系统调用号存入寄存器 a7

之后控制权来到 kernel 中的 syscall 函数,它从 a7 中取出系统调用号,并执行系统调用号对应的 sys_func

这里的系统调用号可以理解为数组索引,在本次 Lab 中需要我们修改 kernel/syscall.ckenel/syscall.h 从而添加 trace 对应的系统调用号,以及内核中 trace 对应的 sys_trace 的实现)。

System call tracing

官网的提示其实是比较全面了,按提示处理,即可添加 trace 的系统调用接口:

Run make qemu and you will see that the compiler cannot compile user/trace.c, because the user-space stubs for the system call don't exist yet: add a prototype for the system call to user/user.h, a stub to user/usys.pl, and a syscall number to kernel/syscall.h. The Makefile invokes the perl script user/usys.pl, which produces user/usys.S, the actual system call stubs, which use the RISC-V ecall instruction to transition to the kernel. Once you fix the compilation issues, run trace 32 grep hello README; it will fail because you haven't implemented the system call in the kernel yet.

之后,则需要我们自己在 kernel/syspro.c 中实现真正执行系统调用 trace 所需要执行的操作了:

Lab 给出的提示中提到,我们需要将 trace(int mask) 的参数 mask 参数存放到 proc 结构体中的一个新成员变量中,这里我们直接用 mask 表示,于是,sys_trace 要做的其实很简单,就是取出寄存器 a0 中的地址然后解引用,得到 mask,然后将它赋给 proc 结构体中的 mask

对于取出寄存器 a0 的参数,Xv6 已经给我们封装好了一个函数 argint,参照一下 sys_exit 的实现,以及 int argint(int n, int *p) 的实现,就能知道 argint 如何使用了,第一个参数表示从哪个寄存器中取值,取出来的值放在地址 p 中。

// 修改 syscall.h,添加 #define SYS_trace 22
static uint64 (*syscalls[])(void) = {
    [SYS_fork] sys_fork,
    [SYS_exit] sys_exit,
    [SYS_wait] sys_wait,
    [SYS_pipe] sys_pipe,
    [SYS_read] sys_read,
    [SYS_kill] sys_kill,
    [SYS_exec] sys_exec,
    [SYS_fstat] sys_fstat,
    [SYS_chdir] sys_chdir,
    [SYS_dup] sys_dup,
    [SYS_getpid] sys_getpid,
    [SYS_sbrk] sys_sbrk,
    [SYS_sleep] sys_sleep,
    [SYS_uptime] sys_uptime,
    [SYS_open] sys_open,
    [SYS_write] sys_write,
    [SYS_mknod] sys_mknod,
    [SYS_unlink] sys_unlink,
    [SYS_link] sys_link,
    [SYS_mkdir] sys_mkdir,
    [SYS_close] sys_close,
    [SYS_trace] sys_trace,
};

// syscall for trace
uint64 sys_trace(void) {
    struct proc *to_trace = myproc();
    int mask;
    if (argint(0, &mask) < 0) { // 取出 trace 之后的 mask 参数
        return -1;
    }
    to_trace->mask = mask;
    return 0;
}

然后需要修改 fork(),从而使得子进程也共享同一个 mask,这里很简单,在 fork() 的实现中添加 np->mask = p->mask; 即可。

最后还需要修改 syscall() 函数,从而当系统调用号属于 mask 使能的系统调用号时,按 Lab 要求进行 printf

void syscall(void) {
    int num;
    struct proc *p = myproc();

    num = p->trapframe->a7;
    if (num > 0 && num < NELEM(syscalls) && syscalls[num]) {
        uint64 res = syscalls[num]();
        p->trapframe->a0 = res;
        int mask = p->mask;
        if ((1 << num) & mask) {
            printf("%d: syscall %s -> %d\n", p->pid, name[num], res);
        }
    } else {
        printf("%d %s: unknown sys call %d\n",
               p->pid, p->name, num);
        p->trapframe->a0 = -1;
    }
}

Sysinfo

添加接口的操作同上,我们先实现 sys_sysinfo,由于 sysinfo 接口的参数是个指针(或者说地址),尽管该参数的地址依旧存放于 a0 寄存器中,但是我们不能再使用 argint 了,这里 Lab 给出了提示,参照 sys_fstat 的实现,我们知道了可以使用 argaddr 实现这一操作,a0 中的值被存放于 uint64 addr 中。

之后,我们需要创建一个新的 struct sysinfo 结构体变量 info,然后将统计的 amount of free memory 和 number of processes 存放于这个结构体变量中。

之后,Lab 提示我们使用 copyoutinfo 传递到 user space,其实参照 copyout 的注释就能清楚明白 copyout 是干嘛的,怎么用了。

uint64 sys_sysinfo(void) {
    uint64 addr; // user pointer to struct sysinfo
    if (argaddr(0, &addr) < 0) {
        return -1;
    }
    struct proc *p = myproc();
    struct sysinfo info;
    info.nproc = get_proc_num();
    info.freemem = freemem_size();
    if (copyout(p->pagetable, addr, (char *)&info, sizeof(info)) < 0) {
        return -1;
    }
    return 0;
}

defs.h 中添加 get_proc_numfreemem_size 的 prototype。

分别在 kernel/kalloc.ckernel/proc.c 中实现。统计 amount of free memory,从 kalloc.c 中可以发现,Xv6 是使用 external free memory list 的形式来进行 malloc 的,所以我们只需要统计 free memory list 的结点数就能知道了;而对统计 number of processes 来说,从 proc.cstruct proc proc[NPROC]; 中可以得知,进程是以数组形式管理的,我们统计该数组中状态不为 unused 即可知 number of processes。

// kernel/kalloc.c
int freemem_size(void) {
    struct run *r;
    int num = 0;
    for (r = kmem.freelist; r; r = r->next) {
        ++num;
    }
    return num * PGSIZE;
}

// kernel/proc
int get_proc_num(void) {
    struct proc *p;
    int num = 0;
    for (p = proc; p < &proc[NPROC]; ++p) {
        if (p->state != UNUSED) {
            ++num;
        }
    }
    return num;
}

总结

这个 Lab 设计得非常精妙,做了 System call tracing 之后,对系统调用的流程就有了比较深刻的理解了,Sysinfo 则是加深理解,两个实验一起,对系统调用时,参数的传入、结果的传出,都有了大致概念。

标签:SYS,trace,mask,Xv6,sys,Lab2,num,proc
From: https://www.cnblogs.com/zwyyy456/p/17551881.html

相关文章

  • Xv6 Lab4
    RISC-VassemblyWhichregisterscontainargumentstofunctions?Forexample,whichregisterholds13inmain'scalltoprintf?a2寄存器,函数调用时,参数从左到右会依次保存在a0,a1,a2,a3寄存器,似乎是一直到寄存器a7的。Whereisthecalltofunctionfinthe......
  • MIT6.5840 lab2,3 记录
    参考链接课程地址如何Debug:没有它可怎么活,几万行的日志怎么看Students'GuidetoRaftraft算法可视化:直观展示raft可视化简单入门raft讲解视频:强烈推荐感想感觉理论+实践来学一个东西才学的深刻,特别是对于我这样对抽象理解不太行的,每次见识了一个算法或系统真正如何运行......
  • Xv6 Lab2
    系统调用Lab1主要是基于提供的系统调用接口来编写一些小工具程序,而Lab2则是要我们自己实现系统调用,并提供系统调用的接口。以本次Lab要我们实现的trace调用为例,说明一下系统调用的流程:在user/trace.c的第$15$行,调用了属于systemcall的trace函数,当前执行makeq......
  • Xv6 操作系统组织架构
    进程概述64位的RISC-V的VAS是39位的,即VA只有39位,而Xv6则只有38位,最大虚拟地址为#defineMAXVA0x3fffffffff。VAS的顶端,即最高位存放了两个page,一个是用于trampoline,一个用于mappingtheprocess'strapframe。Xv6使用这两个page来切换到内核以及返回。......
  • VS2019调用Matlab2019b生成的dll时初始化异常
    在VisualStudio中使用C++调用Matlab程序我目前在写一个用VS和Matlab混编的程序,由于之前的版本(VS2005+MATLAB2010b)太老了,现在想换用VS2019+MATLAB2019b的版本。我原本以为会很简单就能完成配置,没想到在运行时会出现下面的问题。(帧不在模块中。在加载的模块中未找到当前堆栈帧。无......
  • matlab2023a中解方程
    1、matlab中解方程的函数是solve2、查看帮助:helpsolvehelpsolve---sym/solve的帮助---sym/solve-EquationsandsystemssolverThisMATLABfunctionsolvestheequationeqnforthevariablevar.语法S=solve(eqn,var)S=solve......
  • neon linux安装matlab2023a的离线文档
    1.changetodirectorycd/media/munication/59A4D5FD759E19972.mountR2023a_Doc_Linux.isosudomount-oloopR2023a_Doc_Linux.isocdrom/3.changetodirectorycdcdrom/bin/glnxa64/4.installdocsudo./mpminstall-doc--matlabroot=/usr/local/......
  • 【翻译】6.824 lab2 Raft (自用不负责)
    介绍这是系列实验中的第一个,您将在这些实验中构建容错键/值存储系统。在本实验中,您将实现Raft,一个复制状态机协议。在下一个实验中,您将在Raft之上构建键/值服务。然后,您将在多个复制的状态机上“共享”您的服务,以获得更高的性能。复制的服务通过将其状态(即数据)的完整副本存储......
  • 直流微电网模型Matlab2016及以上,功率波动及直流母线电压控制。
    直流微电网模型Matlab2016及以上,功率波动及直流母线电压控制。仅限交流学习~该模型包括:本地松弛母线、光伏系统、电池和直流负载。本地松弛总线使用与交流电网连接的简化VSC转换器。光伏系统采用标准光伏模型+升压转换器。电池采用标准锂离子电池型号+双有源桥式转换器。需求通过......
  • 燃料电池多点恒功率工作Cruise仿真模型!!!本模型基于Cruise2019版及Matlab2018a联合搭建
    燃料电池多点恒功率工作Cruise仿真模型!!!本模型基于Cruise2019版及Matlab2018a联合搭建调试而成,能够按照设定策略正常运行。其中燃料堆控制、电机扭矩控制、再生制动、机械刹车等功能实现基于Matlab/Simulink搭建调试,整车模型基于Cruise完成。ID:96100652450357099......