页表 Page tables
2022-01-16 21:20:03 2022-01-16 87 0
逻辑地址与物理地址的转化
页表是由页表项(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划分部分,换了个名字(大概)