L7:使用虚拟内存

lab通关记录

MIT-6.828实验通关记录

L7:使用虚拟内存

  • 计划:你可以用 vm 做的很酷的事情

    • 更好的性能/效率
      例如,一页填零
      例如,写时复制fork
    • 新功能
      例如,内存映射文件
    • JOS 和虚拟机
    • 本次讲座可能会为最后一个实验室(最终项目)产生想法
  • 虚拟内存:几个视图

    • 主要目的:隔离
      每个进程都有自己的地址空间
    • 虚拟内存提供了一个间接级别
      为内核提供了做很酷的事情的机会
  • 懒惰/按需页面分配

    • sbrk()
      分配虚拟内存,但是只在实际需要的时候page fault,分配物理内存并建立映射
      • page fault:一种中断
        xv6 内存布局讨论
        用户虚拟地址从零开始
        当然用户 va 0 映射到每个进程的不同 pa
        2GB 用于用户堆连续增长
        但不需要有连续的物理内存—-没有碎片问题
        内核和用户映射—-易于切换系统调用、中断
        内核映射到所有进程的同一位置
        简化进程之间的切换
        内核易于读写用户内存
        使用用户地址,例如 sys 调用参数
        内核易于读写物理内存
        pa x 映射到 va x+0x80000000
        我们很快就会在操作页表时看到这一个
  • 退后一步:班级视角

    • 没有一种设计操作系统的最佳方式
      许多操作系统使用 VM,但是可以不用
    • Xv6 和 JOS 展示了操作系统设计的例子
      他们缺乏复杂设计的许多特征
      事实上,与真正的操作系统相比,它们相当蹩脚
      • 我们的目标:教您关键思想,以便您可以推断
        Xv6 和 JOS 是暴露关键思想的最小设计
        你应该能够让他们变得更好
        您应该能够深入了解 Linux 并找到自己的方式
  • 保护页面以防止堆栈溢出

    • 在用户堆栈下方放置一个非映射页面:guard page
    • 如果堆栈溢出,应用程序将看到页面错误
  • 一页填零

    • 内核经常用零填充一个页面
    • 想法:memset函数设置页面为零
      当内核需要零填充页面时映射该页面写时复制:即memset依然只是对虚拟内存操作
      在写入时复制页面并将其映射到应用程序地址空间中的读/写
  • 在 xv6 中共享内核页表
    kvmalloc() 为每个进程的内核页表分配新页
    但所有进程都有相同的内核页表

  • 写时复制fork
    xv6 fork 从父级复制所有页面(参见 fork())

    • 想法:在父子之间共享地址空间
      修改 fork() 以映射页面 copy-on-write(在 PTE 和 PDE 中使用额外的可用系统位)
      在页面错误时,复制页面并将其映射为读/写
  • 需求分页

    • 观察:exec 将完整文件加载到内存中(参见 exec.c)
      这样做需要时间(例如,文件存储在慢速磁盘上)
      不必要:可能不会使用整个文件
    • 想法:按需从文件加载页面
      没必要分配页表条目,但按需标记它们
      出错时,从文件中读入页面并更新页表条目
    • 挑战:文件大于物理内存(见下一个想法)
  • 使用比物理内存大的虚拟内存
    理由:应用程序可能需要比物理内存更多的内存

    • 想法:在磁盘上存储地址空间中不常用的部分
      地址空间的页入页和页出页,这是一个对程序员透明的机制
    • 当工作集适合物理内存时工作
  • 内存映射文件

    • 想法:允许使用加载和存储访问文件
      可以轻松读写文件的一部分
      例如,不必使用 lseek 系统调用更改偏移量,而是直接对虚拟内存修改,然后write系统调用和buffer一次性写文件
    • 按需调入文件页面
      当内存已满时,将不经常使用的文件页面调出:LRU
  • 共享虚拟内存

    • 想法:允许不同机器上的进程共享虚拟内存
      给人一种通过网络共享物理内存的错觉
    • 复制只读的页面:多个虚拟映射同一个物理
    • 在写入时使副本无效
  • JOS 和虚拟内存

    • UVPT 技巧(实验 4)(看本目录下《JOS虚拟内存布局》)
      在 0x3BD 处递归映射 PD
      PD的虚拟地址为(0x3BD<<22)|(0x3BD<<12)
      如果我们想找到虚拟页面 n 的 pte,计算
      pde_t uvpt[n],其中 uvpt 是 (0x3BD << 22)
      = uvpt + n * 4(因为 pdt 是一个词)
      = (0x3BD << 22) | (n 的前 10 位) | (n 的底部 10 位)<< 2
      = 10 | 10 | 12
      例如,uvpt[0] 是地址 (0x3BD << 22),按照指针给我们
      页目录中的第一个条目,它指向第一个页表,它
      我们用 0 索引,这给了我们 pte 0

      这比 pgdirwalk() 更简单,但是实际模拟的时候我们仍然需要走页目录和页表。不过这提供了虚拟页表和物理的方便映射:因为只需要偏移。

    • 用户级写时复制叉(lab4)
      JOS 将页面错误传播到用户空间
      用户程序可以玩与内核类似的 VM 技巧!
      你会做用户级的写时复制叉

Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2020-2024 环烷烃
  • Visitors: | Views:

我很可爱,请我喝一瓶怡宝吧~

支付宝
微信