Lab 10:mmap
实验准备与概述
这次的作业主要考察虚拟内存和文件系统的相关知识,以及两者的综合使用,需要我们在前面实验的基础上进行更进一步的操作,这里面综合了前面诸如lazy lab,cow lab 等实验的操作方法,可以来说是一个综合性题目,当然这里的实现方法有多种,而且各个实现层次的难度亦有不同,下面是比较简单的一种。
这道题主要是要求我们实现两个系统调用:mmap与munmap,我们之前或许了解过这两个函数,主要是进行内存映射,将一个内存区域映射到当前用户进程的区域,而后者则是取消映射。
做了这么多实验,我也发现了做题的思路,要针对实验的测试案例来进行改进,每次实现一个测试案例,然后根据错误提示进行修改即可,直到通过所有的测试案例,屡试不爽哈哈哈哈。
过程可能很漫长,但调试过程也是涉及许多思考的过程,帮助我们成长,对操作系统有更加深入地了解。(我发现我特喜欢打印输出语句,这真的很有帮助哈哈哈)
实验思路
-
首先实现两者的系统调用,返回错误信号(参考syscall的手法,但这里的实现,我放在了sysfile。)
-
深入理解mmap为每个进程映射了哪些东西,也就是VMAs,声明vma,并将VMA数组加入到每个进程中(由于一个进程可能会有多个映射,需要存储这里将最大的存储量设置为NOVMA),也就是说,每个进程会有NOVMA个VMAs,而每个VMA由需要映射的条件(不同数据类型)组成,所以这里将VMA声明为结构体类型,进行数据存储。
#define MINADDR (MAXVA-18*PGSIZE) #define NOVMA 16 struct vma{ uint64 va; uint64 len; int prot; int flags; struct file* f; int offset; }; struct proc { struct spinlock lock; // p->lock must be held when using these: enum procstate state; // Process state struct proc *parent; // Parent process void *chan; // If non-zero, sleeping on chan int killed; // If non-zero, have been killed int xstate; // Exit status to be returned to parent's wait int pid; // Process ID // these are private to the process, so p->lock need not be held. uint64 kstack; // Virtual address of kernel stack uint64 sz; // Size of process memory (bytes) pagetable_t pagetable; // User page table struct trapframe *trapframe; // data page for trampoline.S struct context context; // swtch() here to run process struct file *ofile[NOFILE]; // Open files struct inode *cwd; // Current directory char name[16]; // Process name (debugging) struct vma vmas[NOVMA]; };
-
实现mmap:这里是第一关,首先将获取外部的输入,然后判断外部输入是否合理,接着在当前进程中找到一个空槽VMA,然后将外部输入放入该空槽中,最后返回该空槽存储文件指针的地址,也就是VMA->va(补充说明:这里面涉及如何查找空槽以及如何分配存储文件内容的地址,具体实现如下)
uint64 sys_mmap(void){ struct file *f; uint64 addr; uint64 len; int prot; int flags; int offset; struct vma *v = 0; if(argaddr(0,&addr)<0||argaddr(1,&len)<0||argint(2,&prot)<0||argint(3,&flags)<0||argfd(4,0,&f)<0||argint(5,