xv6---Lab3: page tables

2023-05-16

目录

 参考资料

RISC -V页表的简化图如下所示

​编辑​

多级页表

xv6内核页表

3.6 Process Address Space

3.7 Code: Sbrk

3.8 Code: Exec

Print a page table

A kernel page table per process

hints

copyin/copyout


 参考资料

  • 什么是pagetable?

程序在系统上执行,操作的是虚拟内存地址,而虚拟内存到物理内存的映射需要一个函数f(var1, var2);  其中var1是页表,而var2是偏移量,于是当需要操作一个变量的时候,操作系统可通过函数f(var1, var2); 得到虚拟内存对应的物理内存。

  • 一级页表==》64位的机器消耗的内存过大==》多级页表来减少开销。
  • 参考:Chapter 3: Page Tables - 知乎
  • ​​

     系统之上的内存分配叫虚拟内存,通过内核的MMU单元去管理并映射到物理内存。这是额外的话题。

  • 一种内存空间管理方法是分页,将空间切成固定长度的分片,每个固定长度的单元我们称之为页Page,然后我们将物理内存看成是定长槽块的阵列,这些槽块大小与页相同,每个槽块叫做页帧Page Frame。

  • 一般的分页硬件如下图,在MMU中实现这些分页硬件。

 

​​

 

  

  • RISC-V指令(用户指令或内核指令)对虚拟地址进行操作,物理地址则是用于寻址实际物理内存RAM的(RISC-V可以处理64位的虚拟地址,而物理地址只被设计成56位)

RISC -V页表的简化图如下所示

。。

e68bccb5b225fd2fe0202d7b4fb76b9f.png

  1. 虚拟地址通过页表找到实际的物理内存,一般一个页表的大小设计为4K
  2. xv6运行在Sv39 RISC-V处理器上,64位虚拟地址中,只有低39位在被使用,剩下的25位都暂时保留,供日后的设计者利用。
  3. 将每个虚拟地址映射到一个物理地址,页表会以某种形式的表项来保存这种映射关系,这种表项我们称之为页表条目PTE(Page Table Entry)
  4.  PTE == 44位的物理页帧号PPN (physical page number)+10位的标志位Flags。有效位为54位的PTE可以用8B的大小来存储,这刚好是一个uint64类型。
  5. 虚拟地址 == 25位的EXT:未使用 + 27位的Index:索引对应的PTE+ 12位offset:页内偏移量
  6. 单级页表查询方式:传入一个64位的虚拟地址,通过高27位的index找到在Page Table的位置,即PPN+Flags ==》再通过Flags检查权限 ==》PPN + offset 得到有效的物理地址==>访问物理地址 

多级页表

format,png

  1. 一共有三级,整体上是一个树形的结构。
  2. 页表被设计为刚好一页的大小(4KB),如果整页的PTE都不存在/无效,就完全不分配该页来装载页表。为了跟踪装载页表的页是否有效,引入页目录PD(Page Directory)
  3. 一个PTE占8B的空间,而一个页表大小为4KB,所以一个页表最多存4KB/8B = 512个PTE。故需要9位来找到页表的每一个PTE,从0~511,即2^9
  4. 查找过程:通过L1查找1级页表的PTE==> 得到二级页表的位置==>通过L2找到二级页表的PTE===》找到三级页表位置===>通过L3找到3级页表的PTE==>得到physical address==> 配合offset得到实际的物理地址。 

xv6内核页表

  • xv6为内核单独维护了一个页表,下图展示了内核的虚拟地址空间如何映射到实际的物理地址空间中。format,png
  1. 由上图可见:KERNBASE到PHYSTOP才对应真正的DRAM芯片,代码也是从KERNBASE到PHYSTOP的内存
    // the kernel expects there to be RAM
    // for use by the kernel and user pages
    // from physical address 0x80000000 to PHYSTOP.
    #define KERNBASE 0x80000000L
    #define PHYSTOP (KERNBASE + 128*1024*1024)
  2. KERNBASE的下方访问相应的物理地址,实际上是直接访问相关I/O设备的控制寄存器
  3. 在内核启动未使用页表的时候,内核的虚拟地址到实际的物理地址采用直接映射的方法,内核开始使用页表,会把这种直接映射的关系存到页表。
  • 用户为每个进程分配页表

3.6 Process Address Space

使用页表的好处:

  1. 用户进程现在都有自己的页表,在进程之间提供了隔离性
  2. 用户的虚拟地址空间是连续的,而对应的物理帧分布可以是不连续的。
  3. 通过页表,内核可以将trampoline页映射到用户虚拟地址空间的顶端,所有进程都可以看到这一页。

用户栈的初始内容是由系统调用exec产生的

  • 在初始的用户栈上包括了:各命令行参数的字符串,指向各命令行参数的指针数组argv[ ],用于从调用main(argc, argv[ ])返回的其它参数(argc、argv指针和伪造的返回pc值)。在初始用户栈的内容被设置好之后,用户程序就返回并开始执行main函数。
  • 为了防止用户栈溢出,在栈的下面也放置了一页保护页。栈溢出时会访问到该保护页,从而出现缺页错误异常,用户进程因此陷入内核并等待处理,内核可能会终止掉该进程。

3.7 Code: Sbrk

Sbrk是一个系统调用,用户进程调用它以增加或减少自己拥有的物理内存(proc->sz)

3.8 Code: Exec

现在我们来看最后一段代码,系统调用exec的实现(kernel/exec.c),系统调用exec将存储在文件系统上的,新的用户程序装载进内存里,然后执行它。

int exec(char *path, char **argv)

exec通过路径名打开文件,然后读取该文件的ELF Header(kernel/elf.h)

  • ELF二进制文件 = ELF Header + Program Section Headers,每个Program Section Header都对应一段需要加载到内存中的程序

Print a page table

  • 需要理解xv6是用的三级页表,通过一级页表--》二级页表--》三级页表
  • 根据页表级数打印..   参考freewalk函数得知如何遍历页表。
  • 代码实现:https://gitee.com/mm526830lbw/xv6-labs-2020/compare/0f9135b603835dbd7fa5ef362a1ba774caf7970a...3ce192a90ea0bbaa8e9264dac392172a0830e36e

A kernel page table per process

hints

  • 为新进程生成内核页表的一种合理方法是实现修改过的kvminit版本,它生成新的页表,而不是修改kernel_pagetable。您需要从allocproc调用这个函数。 
  • 将进程的内核页表加载到内核的satp寄存器中:模仿kvminithart()函数
  • scheduler调度器执行用户进程的时候,启用内核页表:把proc->kernel_pagetable装入SATP寄存器。 用户进程执行结束:用系统的页表。
  • kvmpa去读取页表的pte的时候:应该用proc->kernel_pagetable,因为此时算进程在运行,所以该用proc->kernel_pagetable
  • 程序从main.c启动,进入userinit(); 并启动程序sh。
  1. 内核也是一个main程序,所有的程序都是从第一个程序inint.c作为第0个程序开始的,t通过initcode去执行init程序,
  2. 然后init程序回去fork(),再去启动程序sh, 然后就有了人机交互的shell终端
  3. main.c程序会进入scheduler()去调度进程:大概是选一个状态为RUNNABLE的程序A,然后切换为RUNNING状态,在通过函数swtch()来执行程序A。
  • 要理解freeproc ,就需要理解allocproc是如何调用的,
  1. allocproc的调用在fork()【父进程生成子进程】和userinit()函数【初始化的时候,创建第0个进程】
  2. procinit()规定了kernel最多可以有NPROC, 共64个进程,然后每个进程初始化会通过kalloc取得一片物理内存,将整片物理内存,分配到每个进程。

  3. 而allocproc则是在这初始化的64个进程中挑一个状态为RUNNABLE的程序,通过kalloc为之分配trapframe和进程页表

  4. 那么freeproc则是:(1) 释放进程的页表 :即让虚拟内存和物理地址不在有映射关系proc_freepagetable(p->pagetable, p->sz);    (2)通过kfree释放trapframe对应的内存

  • 以fork出子进程为入口点,参考pagetable = proc_pagetable()操作,可知:
  1. 通过kalloc()分配一页页表。再执行mappages操作执行TRAMPOLINE和TRAPFRAME映射操作。
  2. mappages函数:通过walk函数从虚拟地址得到物理地址。前两个页目录设为有效的PTE_V, 最后一页设置为传入的权限参数。
  • 如果需要为进程分配一个和内核一样的页表,那么需要参考内核页表的分配过程
  1. kvminit()是内核栈的初始化,这里可理解为逻机除运行程序之外,需要的外设,中断,程序运行需要的寄存器等等。

  2. 那么同理:进程需要额外的页表,来为每个进程执行一样的映射,映射到外设,中断,程序运行需要的寄存器等等。只不过需要放到进程proc结构体里的kernel_pagetable。

  3. 关于free操作,在页表初始化映射了什么,就free什么,类似malloc和free是一对操作。

  • 参考:xv6-lab3-pgtbl_Wound+=s的博客-CSDN博客
  • 参考:Mit6.S081-实验3-Page tables_解析Ta的博客-CSDN博客_page tables

copyin/copyout

理解的不是很透彻,大多数的理解都放在代码里了。加了很多注释

https://gitee.com/mm526830lbw/xv6-labs-2020/tree/pgtbl/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

xv6---Lab3: page tables 的相关文章

  • windows10更新蓝屏 错误代码:page fault in nonpaged area

    现象 xff1a windows10更新蓝屏 错误代码 xff1a page fault in nonpaged area 一般在71 重启是发现 xff0c 然后重启两次后出现恢复原系统 xff0c 更新失败 失败原因 xff1a 软件不
  • #最详细# Github Page 个人博客绑定二级域名

    文章目录 1 必要条件 xff1a 2 操作步骤 xff1a 3 操作3 1 在阿里云控制台添加子域名解析记录3 2 在 Github 中修改配置 1 必要条件 xff1a 已申请个人域名已配置好Github Page 2 操作步骤 xff
  • OrCAD关闭start page

    打开原理图工具 Orcad Capture CIS 时 xff0c 总是会弹出startpage 页面 xff0c 有时候感觉这个东西挺碍事的 xff0c 于是找到了一个关闭它的方法 解决方法如下 xff1a 打开Command Windo
  • Github Page 个人主页——CDN加速

    原文地址 1 前言 前两篇文章介绍了 如何部署静态网站 以及 给网站自定义域名 xff0c 到目前为止 xff0c 您已经拥有一个使用自己的域名的网站了 在访问个人网页时 xff0c 实质上是去Github的服务器上取资源的 xff0c 但
  • Github Page 个人主页——Hexo博客

    原文地址 一 前言 在前三篇文章介绍了如何部署一个属于自己的站点网页 xff0c 但是只有个人主页有些单调 xff0c Github Page 的本质是部署web站点 xff0c 所以不仅可以部署个人主页 xff0c 还可以将自己的博客部署
  • postgresql page页结构

    前言 postgresql 保存数据的基本单位是 page xff0c 一个 page 里包含多条数据 postgresql 同磁盘的读写单位也是 page xff0c 一个 page 对应于磁盘的一个 block block 的格式和 p
  • 使用Laravel提交POST请求出现The page has expired due to inactivity错误

    使用Laravel提交POST请求出现The page has expired due to inactivity Please refresh and try again 问题 提交POST请求 xff0c 出现如下错误 xff1a Th
  • 破解modelsim之后电脑蓝屏出现的PAGE_FAULT_IN_NONPAGE,hardlock.sys错误

    我折腾了一上午终于弄好了X X 之前卸载了modelsim但是没删掉hardlock sys xff0c 一直蓝屏显示错误 1 首先长按电源键10s关机后开机 xff0c 扫一下这个二维码 xff0c 根据里面的提示进入安全模式 xff08
  • lvgl page manage 代码学习

    64 file lv 100ask page manager c INCLUDES include 34 lv 100ask page manager h 34 if LV USE 100ASK PAGE MANAGER 61 0 DEFI
  • xv6调试

    窗口1作为xv6的运行窗口 make CPUS 61 1 qemu gdb 窗口2作为gdb调试窗口 gdb multiarch kernel kernel 进入gdb后执行 set confirm off set architecture
  • linux/mm/memory.c/free_page_tables()

    看linux0 11的源码有一段时间了 xff0c 发现前期的轮廓建立起来后 xff0c 重点马上到了具体操作上 即函数 xff0c 毕竟OS本身是由一系列函数组成的 xff0c 源码面前了无秘密 xff0c 所以要深刻理解操作系统的神奇
  • linux/mm/memory.c/put_page

    put page用来完成物理页面与一个线性地址页面的挂接 xff0c 从而将一个 线性地址空间内的页面落实到物理地址空间内 xff0c copy page tables函数 只是为一个进程提供了在线性地址空间的一个页表及1024页内存 xf
  • linux/mm/memory.c/int share_page(unsigned long address)

    share page tries to find a process that could share a page with the current one Address is the address of the wanted pag
  • xv6---Lab3: page tables

    目录 参考资料 RISC V页表的简化图如下所示 编辑 多级页表 xv6内核页表 3 6 Process Address Space 3 7 Code Sbrk 3 8 Code Exec Print a page table A kern
  • page_cleaner

    MySQL Error Log 中IO写入瓶颈的警告分析 在一台MySQL实例上频繁做大批量的写入测试 xff0c 无意中发现MySQL的errorlog中频繁出现如下的Note xff1a page cleaner 1000ms inte
  • 汉字编码标准与识别(一)代码页(Code Page)初识

    BBS水木清华站 精华区 发信人 yanglc 魂归燕园 别理我 xff0c 烦着呢 信区 Linux 标 题 汉字编码标准与识别 一 发信站 BBS 水木清华站 Sat Apr 29 17 19 05 2000 http www linu
  • 把握linux内核设计思想(十一):内存管理之页的分配与回收

    版权声明 尊重原创 转载请保留出处 blog csdn net shallnet 文章仅供学习交流 请勿用于商业用途 内存管理单元 MMU 负责将管理内存 在把虚拟地址转换为物理地址的硬件的时候是按页为单位进行处理 从虚拟内存的角度来看 页
  • 数字后跟大写 L

    什么是512L意思是 或者可能是任何数字后跟大写 L example uint sec然后是一些带有表达式的代码 sec 512L 取出来的XV6代码 mkfs c L代表long 这创建了一个类型的文字long l也可以 但看起来像1 所
  • 声明“extern struct cpu *cpu asm("%gs:0");”是什么意思意思是?

    当我阅读 xv6 源代码时 我对下面声明的语法感到困惑 谁能给我解释一下吗 extern struct cpu cpu asm gs 0 我假设你明白什么extern struct cpu cpu方法 你的问题是 asm gs 0 部分意思
  • 为什么ELF的vaddr没有页面对齐?

    我正在尝试构建一个类似 xv6 的系统 并且我正在复制下面的 xv6 代码 if ph p vaddr PGSIZE cprintf exec addr not page aligned n goto bad 这是ELF被加载到内存的部分

随机推荐

  • core dumped ?完了?

    微信公众号 xff1a linux码头 core dumped xff1a 当程序在运行过程中发生异常 xff0c 这时linux系统可以把程序出错的内存 内容存储在一个core文件中 xff0c 又叫核心转存 应用程序在运行过程汇总经常会
  • Ubuntu18.04安装网络调试助手 NetAssist

    下载地址 链接 xff1a https pan baidu com s 1DUqZBtxFh pGTsRR2kXaPA 提取码 xff1a fp32 安装步骤 1 xff09 建立依赖关系 sudo apt get install f 2
  • C语言中左移(<<)和右移(>>)的理解

    lt lt 左移 xff1a 相当于乘法 a lt lt b 61 a 2 b 举例 xff1a 1 lt lt 5 xff0c 相当于1 2 5 61 32 1 lt lt 0 xff0c 相当于1 2 0 61 1 gt gt 右移 x
  • 《Linux运维总结:firewalld防火墙使用教程》

    文章目录 一 firewalld基础知识1 1 firewalld基本介绍1 2 firewalld与iptables关系与区别1 3 firewalld默认策略1 4 firewalld配置模式1 5 firewalld配置方法1 6 f
  • ROS常用的功能包

    坐标系 坐标变换 xff08 tf xff09 tf功能包提供了一个基于ROS的分布式框架 xff0c 可以随着时间的推移计算多个坐标系的位置 3D可视化工具 xff08 rviz xff09 机器人模型的可视化 图像数据的可视化 地图数据
  • 树莓派4B+Ubuntu 18.04 LTS + 桌面desktop + ros安装@树莓派4B、Ubuntu、desktop、ros

    树莓派4B 43 Ubuntu 18 04 LTS 43 桌面desktop 43 ros安装 64 树莓派4B Ubuntu desktop ros 久违的一篇博客 xff0c 说实话CSDN的编辑器还是用不太习惯 xff0c 记录一下树
  • 云台控制协议总结(VISCA/PELCOD/PELCOP)

  • error: #20: identifier "TIM_TimeBaseInitTypeDef" is undefined

    如果出现多句错误 xff1a identifier 34 34 is undefined 解决问题方法一 xff1a C C 43 43 include paths 把文件路径添加进去 解决问题方法二 xff1a 在stm32f10x co
  • 使用pyqt5实现键盘(含组合键)鼠标事件响应

    使用pyqt5实现键盘 xff08 含组合键 xff09 鼠标事件响应 使用python3 6 xff0c pyqt5 xff0c 在macOS上测试有效 span class hljs keyword import span sys sp
  • 递归思想刷题总结

    核心思想 我们在调用递归函数的时候 xff0c 把递归函数当做普通函数 xff08 黑箱 xff09 来调用 xff0c 即明白该函数的输入输出是什么 xff0c 而不用管此函数内部在做什么 xff08 千万不要跳进去了 xff0c 你脑袋
  • anonymous unions are only supported in --gnu mode, or when enabled with #pragma anon_unions

    在keil工程下移植代码 xff0c 编译出现了这个问题 xff0c 字面上解决办法有 xff1a 1 打开GNU模式 option gt GNU extensions 2 在代码前加上 pragma anon union 就是代表支持匿名
  • 串口的深入理解

    1 串口是如何发送数据的 xff1f 一般说来 xff0c 串口发送数据是往数据寄存器sbuf填写数据 xff0c 一个字节一个字节的写入 xff0c 如果有串口中断 xff0c 那么发送完一个字节的数据 xff0c 就会进入串口中断一次
  • CMakeLists.txt的简单使用

    Makefile和CMakeLists的关系 环境准备 xff1a 需要安装gcc xff0c g 43 43 xff0c make sudo apt get install gcc g 43 43 sudo apt get isntall
  • .so文件的基本理解,使用。

    一 基本概念 Linux下的 so是基于Linux下的动态链接 其功能和作用类似与windows下 dll文件 代码编译 xff0c 链接 xff0c 最后生成可执行文件 xff1b 这个可执行文件就可看作是一个静态链接 xff0c 因为代
  • jz2440:QT控制LED灯点亮熄灭(11)

    1 LED灯的驱动 xff1a 首先要准备好在驱动文件 xff0c 通过insmod led ko来加载模块 xff0c 然后在QT的代码里面配合调用open xff0c write read函数来点亮 xff0c 关闭LED灯 这一步 x
  • win10下安装ubuntu双系统

    本文章记录自己在Win10系统下安装ubuntu双系统的过程 xff0c 以及注意事项 另一个不错的安装教程 1 下载系统镜像 在官网或清华镜像 xff0c 根据需要的ubuntu版本下载需要的ubuntu镜像文件 这里要注意 xff0c
  • C++ shared_ptr的reset 用法

    include lt iostream gt include lt memory gt class Tmp public Tmp int a Tmp void print a std cout lt lt 34 value 61 34 lt
  • C++ 模板类的继承

    模板类 xff1a template lt typename T gt 说白了就是向之后的内容传递参数类型 xff0c 把T当作一个数据类型传递 xff0c 而在声明一个变量的时候 xff0c 通过base lt xxxx gt pp xx
  • linuxptp源码研究

    目录 1 检查网卡是否支持相应的时间戳 2 linuxptp的目录架构 3 ptp4l的大致流程分析 4 gptp协议对应的sync follow up delay request delay response消息在代码的位置 5 slav
  • xv6---Lab3: page tables

    目录 参考资料 RISC V页表的简化图如下所示 编辑 多级页表 xv6内核页表 3 6 Process Address Space 3 7 Code Sbrk 3 8 Code Exec Print a page table A kern