Speed up system calls
第一个任务,是加快系统调用
正常情况下,我们要getPid什么的,需要去调用内核函数才能获取,但是我们把这些信息直接放进page中。
即在proc中去添加可以映射到USYSCALL的页,这个USYSCALL其实是一个只包含pid的结构体
使得我们从用户态就可以直接快速访问pid,就不需要再进行用户态到内核态的转换了
Detecting which pages have been accessed
这个练习要求我们写一个检测某个页面是否已经访问过的系统调用
实验要求:从一个用户页表地址开始,搜索所有被访问过的页并返回一个bitmap来显示这些页是否被访问过。比如说,如果第二个页被访问过了,bitmap里从右往左数第二个bit就是1。
我们需要明确,PTE_A标志位虽然是我们自己新添加的,但是只要访问过该页,硬件会自动把它置为1。
核心代码
intsys_pgaccess(void) {// lab pgtbl: your code here.uint64 addr;int len;int bitmask;if (argaddr(0, &addr) < 0) { // 内核函数取调用者的参数方法就是这样return -1;}if (argint(1, &len) < 0) {return -1;}if (argint(2, &bitmask) < 0) {return -1;}if (len > 32 || len < 0) {return -1;}/*** 核心代码* 用int va = addr + i * PGSIZE表示某个页表的第i个的虚拟地址* 使用vm_pgaccess去找这个虚拟地址对应的标志位* 用res | abit << i把标志位加到res中对应i的位置* 最后再把res拷贝到bitmap中,返回给调用的用户进程*/int res = 0;struct proc *p = myproc();for (int i = 0;i < len;i++) {int va = addr + i * PGSIZE;int abit = vm_pgaccess(p->pagetable, va);res = res | abit << i;}if (copyout(p->pagetable, bitmask, (char *)&res, sizeof(res)) < 0) { // Copy from kernel to user.return -1;}return 0;}
int vm_pgaccess(pagetable_t pagetable, uint64 va) {pte_t *pte;if (va >= MAXVA) {return 0;}pte = walk(pagetable, va, 0);if (pte == 0) {return 0;}if ((*pte & PTE_A) != 0) {*pte = *pte & (~PTE_A); // clear 6th flag(PTE_A)return 1;}return 0;}
