page_table

简述

page table,页表

页表的功能:将虚拟地址转换成物理地址

设置内核空间页表的过程

main()中设置内核空间页表的过程,如下:

  1. 调用kvminit()设置内核空间页表的衡等映射,比如UART0的物理地址0x10000000L对应的虚拟地址也是0x10000000L

  2. 由于XV6采用三级页表的方式进行管理,调用kvminithart() -> w_satp()将第一级页表(根页表)的起始地址存储到SATP寄存器中,同时激活分页功能(Risc-V架构),但是因为第一步将内核空间的页表设置成衡等映射,所以对内核空间来说,激活分页功能后,执行下一条指令没有影响

    注意:

    执行此指令之前,所有的地址都是物理地址

    执行完此指令后,所有的地址都是虚拟地址

  3. 调用kvminithart() -> sfence_vma()刷新TLB

将 用户空间虚拟地址内容 复制到 内核空间虚拟地址 的过程

此处以int write(int pid, const void *buf, int size)为例子,如下:

当用户空间调用write()时,通过ecall陷入内核空间,详细解释看traps 文档。注意:write()实现函数由汇编语言编写而成(user/usys.S,此文件需要编译后才自动产生)

接着调用uservec() -> usertrap() -> syscall(),通过系统启用号(如:SYS_write),调用sys_write(),通过寄存器x0~x2得到由用户空间传递到内核空间的参数,调用filewrite() -> pipewrite() -> copyin(user_pagetable),然后通过用户空间页表将用户空间虚拟地址转换成对应的物理地址,最后将物理地址的内容复制到内核空间的虚拟地址

如果将用户空间页表内容 映射到 内核空间页表(不是复制),调用copyin()时,就不需要通过用户空间页表将用户空间虚拟地址转换成对应的物理地址,直接将用户空间虚拟地址的内容复制到内核空间的虚拟地址

最后,从 内核空间 返回到 用户空间,调用sys_write() -> syscall() -> usertrapret() -> userret(), 返回到ecall下一条指令继续执行

Last updated

Was this helpful?