逻辑地址与物理地址的转化

页表是由页表项(PTE)组成的数组。512个PTE构成一个页表页(Page-table page)。

PTE中包含了物理页码(PPN physical page number)以及一些标志,来控制物理空间块的读写访问权限。

物理地址与虚拟地址的映射为三层树形结构,每一层存储下一层页表页的地址,最后一层存储物理地址的PTE。

(个人理解:计算机中的物理地址被逻辑性理解成了页面+偏移量,其本质没发生变化,依旧是某一内存单元的编号)

​ 图 PTE的格式

代码解析

walk函数用来获得逻辑地址(va virtual address)的所在物理地址(pa physical address)的PTE (一般都是对整个page做操作,很少有对某个特定地址进行操作,所以是获得该va所在page的PTE,主要操作包括对其标志位进行处理)

主要展示了逻辑地址是如何转换成物理地址的,这是分页机制最核心的一个部分

page和上篇exec提到的segment共同组成计算机中虚拟内存机制

// Return the address of the PTE in page table pagetable
// that corresponds to virtual address va. If alloc!=0,
// create any required page-table pages.
//
// The risc-v Sv39 scheme has three levels of page-table
// pages. A page-table page contains 512 64-bit PTEs.
// A 64-bit virtual address is split into five fields:
// 39..63 -- must be zero.
// 30..38 -- 9 bits of level-2 index.
// 21..29 -- 9 bits of level-1 index.
// 12..20 -- 9 bits of level-0 index.
// 0..11 -- 12 bits of byte offset within the page. //返回逻辑地址va所对应的PTE的指针
pte_t *
walk(pagetable_t pagetable, uint64 va, int alloc)
{
if(va >= MAXVA)
panic("walk"); for(int level = 2; level > 0; level--) {
//PX(level,va) 获取level对应的PTE 如上图的L2
//以L2为例,这里获得了L2在第三级页表页中位置编号
//相当于物理地址的偏移量
pte_t *pte = &pagetable[PX(level, va)];
// PTE_V valid 表示PTE是否合法
if(*pte & PTE_V) {
//PTE2PA 将PTE转换成实际的物理地址
//这个物理地址即第二级页表页的起始地址
pagetable = (pagetable_t)PTE2PA(*pte);
} else {
//如果PTE_V=0 说明第二级页表页还未创建,则创建一个
if(!alloc || (pagetable = (pde_t*)kalloc()) == 0)
return 0;
//用0填充
memset(pagetable, 0, PGSIZE);
//然后将PTE_V置 1
*pte = PA2PTE(pagetable) | PTE_V;
}
} return &pagetable[PX(0, va)];
}

附:

typedef uint64 pte_t;
typedef uint64 *pagetable_t; // 512 PTEs // extract the three 9-bit page table indices from a virtual address.
#define PXMASK 0x1FF // 9 bits
#define PXSHIFT(level) (PGSHIFT+(9*(level)))
#define PX(level, va) ((((uint64) (va)) >> PXSHIFT(level)) & PXMASK) #define PTE_V (1L << 0) // valid
#define PTE_R (1L << 1)
#define PTE_W (1L << 2)
#define PTE_X (1L << 3)
#define PTE_U (1L << 4) // 1 -> user can access // shift a physical address to the right place for a PTE.
#define PA2PTE(pa) ((((uint64)pa) >> 12) << 10) #define PTE2PA(pte) (((pte) >> 10) << 12)

可执行文件以节section划分部分,载入内存后,以段segment划分部分,换了个名字(大概)

页表 Page tables的更多相关文章

  1. PatentTips - Substitute virtualized-memory page tables

    BACKGROUND Many computer systems utilize virtualized memory for security, stability and/or other pur ...

  2. PatentTips - Maintaining shadow page tables in a sequestered memory region

    BACKGROUND Malicious code, known as malware, which includes viruses, worms, adware, etc., may attack ...

  3. Extended paging tables to map guest physical memory addresses from virtual memory page tables to host physical memory addresses in a virtual machine system

    A processor including a virtualization system of the processor with a memory virtualization support ...

  4. linux thtree level page tables

    To translate a virtual address into a physical one, the CPU must take the contents of each level fie ...

  5. 【译】x86程序员手册39-10.3切换到保护模式

    10.3 Switching to Protected Mode  切换到保护模式 Setting the PE bit of the MSW in CR0 causes the 80386 to b ...

  6. 【硬核】MMU是如何完成地址翻译的

    目录 1. 什么是虚拟内存? 2. 虚拟内存的作用 3. 虚拟内存与物理内存 3.1 CPU存取数据 3.2 物理地址常用术语 3.3 虚拟地址常用术语 3.4 页表常用术语 3.5 页命中/缺页 4 ...

  7. Operating System Memory Management、Page Fault Exception、Cache Replacement Strategy Learning、LRU Algorithm

    目录 . 引言 . 页表 . 结构化内存管理 . 物理内存的管理 . SLAB分配器 . 处理器高速缓存和TLB控制 . 内存管理的概念 . 内存覆盖与内存交换 . 内存连续分配管理方式 . 内存非连 ...

  8. 临时2级页表的初始化过程 head_32.S 相关代码解释

    page_pde_offset = (__PAGE_OFFSET >> 20); /* __PAGE_OFFSET是0xc0000000,page_pde_offset = 3072 = ...

  9. linux内存管理解析1----linux物理,线性内存布局及页表的初始化

    主要议题: 1分页,分段模式及实模式 2Linux分页 3linux内存线性地址空间布局及物理内存空间布局 4linux页表初始化及代码解析 1.1.1内存寻址和保护模式 在X86平台上,内存控制单元 ...

随机推荐

  1. SpringMVC执行流程总结

    SpringMVC 执行流程: 用户发送请求至前端控制器 DispatcherServlet DispatcherServlet 收到请求调用处理映射器 HandlerMapping 处理映射器根据请 ...

  2. pip更新升级和删除包

    pip检测更新命令:pip list –outdated pip升级包命令:pip install --upgrade packagename pip卸载包命令:pip uninstall packa ...

  3. scrum项目冲刺_day05总结

    摘要:今日完成任务. 1.语音识别完成 2.搜索功能实现了从数据库中的查询 总任务: 一.appUI页面(已完成) 二.首页功能: 1.图像识别功能(已完成) 2.语音识别功能(已完成) 3.垃圾搜索 ...

  4. 一些PHP选项参数相关的函数

    关于 PHP 的配置,我们大多数情况下都是去查看 php.ini 文件或者通过命令行来查询某些信息,其实,PHP 的一些内置函数也可以帮助我们去查看或操作这些配置参数.比如之前我们学习过的 关于php ...

  5. Dapr实战(二) 服务调用

    服务调用是什么 在分布式应用程序中的服务之间进行调用会涉及到许多挑战. 例如: 维护其他服务的地址. 如何安全地调用服务. 在发生短暂的 暂时性错误 时如何处理重试. 分布式应用程序调用链路追踪. 服 ...

  6. disruptor笔记之三:环形队列的基础操作(不用Disruptor类)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  7. navicat导出DDL语句

    工作中有的时候需要将某个库中的表.视图.函数.存储过程等创建语句导出,又不需要表中的数据. 方法一:需要拷贝的创建语句条数不多,可以选择直接拷贝DDL语句 方法二:使用Navicat的备份功能

  8. AT3611-Tree MST【点分治,最小生成树】

    正题 题目链接:https://www.luogu.com.cn/problem/AT3611 题目大意 给出\(n\)个点的一棵树. 现在有一张完全图,两个点之间的边权为\(w_x+w_y+dis( ...

  9. pandas 基础命令

    参考链接:https://github.com/rmpbastos/data_science/blob/master/_0014_Boost_your_Data_Analysis_with_Panda ...

  10. Python - __all__ 变量

    import * 当我们向文件导入某个模块时,导入的是该模块中那些名称不以下划线(单下划线 _ 或者双下划线 __ )开头的变量.函数和类 因此,如果不想模块文件中的某个对象被引入到其它文件中使用,可 ...