首页 > 其他分享 >【XV6】 page tables

【XV6】 page tables

时间:2024-02-14 19:13:29浏览次数:38  
标签:tables pagetable int PTE page 页表 XV6 pte 页面

代码:https://github.com/JasenChao/xv6-labs.git

快速获取pid-ugetpid

题目要求参考已实现的ugetpid()使用USYSCALL快速获取pid

实现的思路是在每一个进程中增加一个共享页面,通过USYSCALL指定的虚拟地址,找到指定的页面。参考进程中的Trampoline页Trapframe页。Trampoline页保存进出内核的代码,Trapframe页保存寄存器的数据。

proc.h文件中的struct proc中增加成员struct usyscall *sc

proc.c文件中的allocproc()函数中,模仿struct trapframe,加入以下代码,申请内存并把pid保存下来:

if((p->sc = (struct usyscall *)kalloc()) == 0){
    freeproc(p);
    release(&p->lock);
    return 0;
}
p->sc->pid = p->pid;

对应地修改freeproc函数,释放内存空间:

if(p->sc)
    kfree((void*)p->sc);

proc.c文件中的proc_pagetable函数中,增加USYSCALLPTE

if(mappages(pagetable, USYSCALL, PGSIZE,
            (uint64)(p->sc), PTE_R | PTE_U) < 0){
    uvmunmap(pagetable, TRAPFRAME, 1, 0);
    uvmunmap(pagetable, TRAMPOLINE, 1, 0);
    uvmfree(pagetable, 0);
    return 0;
}

每个 PTE 都包含一些标志位,说明分页硬件对应的虚拟地址的使用权限:

  • PTE_V:表示页表项的有效性(valid),即该页表项是否有效。
  • PTE_R:表示可读权限(read),指示对应的页面是否可以被读取。
  • PTE_W:表示可写权限(write),指示对应的页面是否可以被写入。
  • PTE_X:表示可执行权限(execute),指示对应的页面是否可以被执行。
  • PTE_U:表示用户访问权限(user),指示该页表项是否可以被用户级别的程序访问。

对应地修改proc_freepagetable函数,释放内存:

uvmunmap(pagetable, USYSCALL, 1, 0);

打印页表

题目要求可视化RISC-V页表,在启动XV6的时候打印第一个进程的页表。

根据提示在vm.c中实现打印页表功能的函数,可以参考同文件中的freewalk函数,只遍历页表,不要将页表清空即可。代码如下:

static void vmprint_func(pagetable_t pagetable, int level)
{
  for(int i = 0; i < 512; i++){
    pte_t pte = pagetable[i];
    if(pte & PTE_V){
      uint64 pa = PTE2PA(pte);
      for(int j = 0; j < level; ++j) printf(".. ");
      printf("..%d: pte %p pa %p\n", i, pte, pa);
      if (level < 2) vmprint_func((pagetable_t)pa, level + 1);
    }
  }
}

void
vmprint(pagetable_t pagetable)
{
  printf("page table %p\n", pagetable);
  vmprint_func(pagetable, 0);
}

为了让exec函数可以调用以上函数,在defs.h中进行声明:

void            vmprint(pagetable_t pagetable);

exec.c文件中的exec函数返回前增加代码,判断如果pid为1则调用打印页表的功能:

if(p->pid == 1){
    vmprint(p->pagetable);
}

使用make GRADEFLAGS=printout grade命令测试是否通过。

检测已访问的页面

题目要求实现一个系统调用,通过bit位检测页面是否被访问,测试程序pgaccess_test已经给出,用unsigned int abits的32位检测32个页面被访问的情况,置1即为被访问,下面对第1、2和30个页面的内容进行了写操作,正常应该返回abits40000006

先在riscv.h文件中增加#define PTE_A (1L << 6),一开始我按顺序设的5,程序测试不通过,后来发现手册里面必须写6...

再完善sysproc.c文件中的sys_pgaccess函数,函数框架已经给出来了,代码如下:

int
sys_pgaccess(void)
{
  struct proc *p = myproc();
  uint64 addr, mask, va;
  int n;
  unsigned int abits = 0;

  argaddr(0, &addr);
  argint(1, &n);

  va = addr;
  for(int i = 0; i < n; ++i){
    pte_t* pte = walk(p->pagetable, va, 0); // 获取PTE
    if(*pte & PTE_A){
      abits |= 1 << i;
      *pte ^= PTE_A;                        // 如果PTE_A已经置1,需要置为0,避免第二次访问时混淆
    }
    va += PGSIZE;
  }

  argaddr(2, &mask);
  if(copyout(p->pagetable, mask, (char*)&abits, sizeof(abits)) < 0) return -1;
  return 0;
}

使用make GRADEFLAGS=pgaccess grade命令测试结果是否正确。

测试结果

使用make grade测试,结果如下:

== Test   pgtbltest: ugetpid ==
  pgtbltest: ugetpid: OK
== Test   pgtbltest: pgaccess ==
  pgtbltest: pgaccess: OK
== Test pte printout ==
$ make qemu-gdb
pte printout: OK (0.9s)

标签:tables,pagetable,int,PTE,page,页表,XV6,pte,页面
From: https://www.cnblogs.com/JasenChao/p/18015448

相关文章

  • 【XV6】 system calls
    代码:https://github.com/JasenChao/xv6-labs.git使用GDB调试安装risc-v的GDB先安装依赖:sudoapt-getinstalllibncurses5-devpython2python2-devtexinfolibreadline-dev再下载源码,可以从清华镜像源下载:wgethttps://mirrors.tuna.tsinghua.edu.cn/gnu/gdb/gdb-13.2.ta......
  • 【XV6】 Multithreading
    代码:https://github.com/JasenChao/xv6-labs.git用户级线程切换题目要求完成用户级线程系统,提示程序要在uthread.c和uthread_switch.S中补充完成。用户级线程调度和进程的机制是类似的,因此uthread_switch.S可以复制swtch.S中的内容: .globlthread_switchthread_switch:......
  • 【XV6】 Copy-on-Write Fork for xv6
    代码:https://github.com/JasenChao/xv6-labs.gitCopy-on-WriteFork系统调用fork()会复制一个父进程的用户空间到子进程,一方面如果进程较大,复制需要很长的时间,另一方面复制的内存的大部分会被丢弃,造成浪费。题目要求实现写时复制COW来延迟fork的物理内存复制,子进程只创建了一个......
  • 【XV6】 traps
    代码:https://github.com/JasenChao/xv6-labs.gitbacktrace题目要求实现backtrace来对堆栈上调用发生错误的地方进行跟踪。寄存器s0包含指向当前堆栈帧的指针,那么返回地址就位于帧指针的固定偏移量-8,前一个fp地址的偏移量为-16。在riscv.h文件中增加提示中的代码:staticinline......
  • 【XV6】 file system
    代码:https://github.com/JasenChao/xv6-labs.git支持大文件XV6目前只支持268个blocks大小的文件,一个block(BSIZE)为1024,文件块inode包含12个一级地址和1个二级地址,二级地址指向另一个block,其中存放了256个一级地址,因此一共是268个。题目要求支持大文件(65803个blocks),提示通过三级......
  • 【XV6】 locks
    代码:https://github.com/JasenChao/xv6-labs.git内存分配器单个空闲内存列表可能引起多个CPU的频繁锁争用,题目要求设计内存分配器,让每个CPU维护一个空闲内存列表,不同CPU的分配和释放可以并行执行,但如果一个CPU可用列表为空,而其他CPU可用列表不为空,则这个CPU必须窃取其他CPU的空......
  • 【XV6】 networking
    代码:https://github.com/JasenChao/xv6-labs.gitE1000网络设备驱动题目已经在kernel/e1000.c中给出了E1000的初始化函数和发送接收函数,要求完善发送和接收的功能。其他相关的代码,上层的网络协议在kernel/net.c和kernel/net.h中。PCI总线上搜索网卡的代码在kernel/pci.c中://t......
  • iptables
    iptables是一个基于内核空间netfilter的用户空间工具,用于配置Linux内核的防火墙规则。钩子函数PREROUTING:在进入IP路由之前触发,就意味着只要接收到的数据包,无论是否真的发往本机,也都会触发这个钩子。它一般是用于目标网络地址转换(DestinationNAT,DNAT)。INPUT:报文经......
  • [MIT 6.S081] Lab: Copy-on-Write Fork for xv6
    Lab:Copy-on-WriteForkforxv6在这个实验中,我们要为xv6实现cowfork。Implementcopy-onwrite根据写时复制的方式,我们在复制页面的时候应该采用的是将父级的物理页面映射到子级的页面,因此我们需要修改kernel/vm.c中的uvmcopy,将页面复制修改为映射的方式,同时应当将......
  • 使用iptables拒绝某IP连接本机
    背景在开发工作中,经常遇到需要验证网络策略相关问题。例如是否具有自动重连机制,需要将网络策略先断开,然后放开看服务是否正常运行。在linux系统中可以使用iptables来实现该效果。使用路由规则查看当前系统路由规则iptables-L添加禁止ip访问策略,例如访问ip:192.168.1.......