逻辑地址到物理地址的映射与二级页表

一、首先要区分一下三个地址的概念,分别是逻辑地址,线性地址和物理地址。

逻辑地址:每个逻辑地址由一个段(segment)和偏移量(offset)组成。

线性地址:32位无符号整数,可表示4G大小的地址空间。

物理地址:芯片级内存单元寻址。它们与从CPU的地址引脚发送到内存总线上的电信号相对应。

 

逻辑地址由CPU产生,在32位机器中为32位,CPU利用这个逻辑地址来寻址4G的内存空间。

 

采用内存寻址机制的好处:

1.保护内核不受恶意或者无意的破坏

2.隔离各个用户进程

3.方便程序的编写,使程序员可以抛开对物理内存的考虑,而且理论上可以使用任意大小的空间

 

二、其次区分一下页、页框、块这三个概念。

 

将线性地址空间划分为大小相同的组,称为“页”,一页为4KB大小,即2e12 byte

块:将无力内存划分为大小与页等同的组,称为块,或者针

页框:即块的另一个名字

 所以,页是用来描述逻辑地址空间的,页框或者块是用来描述物理地址空间的

三、一级页表与二级页表

32位的逻辑地址被分为两部分 20 12

20为页号,负责在内存中寻找到对应的块,12为页内偏移

这样计算下来,每个页条目需要4byte来存储(因为要访问4G的内存空间,其中一个存放着块的基地址,加上12为的内页偏移,才完成到物理地址的映射),一共有2e20*4byte=4MB,所以一个页表本身就需要4MB来存储。

 

二级页表:32位的逻辑地址被分为三部分 10 10 12

一级页表有2e10个条目,需要4KB存储,二级页表有2e20个条目,需要4KB存储,所以,采用二级页表,只需要8KB就可以完成页表的存储了。


四、逻辑地址到物理地址的映射

通过采用页表这种机制,在内存中找到最终的块基地址后,与逻辑地址的剩余部分(即偏移地址)组合,就完成了到物理地址的转换。


  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二级分页存储是一种虚拟内存管理技术,它将虚拟地址空间分割成多个大小相等的页,每个页又进一步划分成多个大小相等的页框,而物理内存也被划分成相同大小的页框。当程序需要访问某个虚拟地址时,系统会将该地址转换为对应的物理地址,并将其映射到物理内存中的一个页框中。 下面是一个简单示例,展示如何实现二级分页存储的地址转换: ```c #include <stdio.h> #include <stdlib.h> #define PAGE_SIZE 1024 // 每页大小为1024字节 #define PAGE_NUM 64 // 虚拟地址空间大小为64页 #define FRAME_NUM 32 // 物理内存大小为32页框 // 页表项结构体 typedef struct { int valid; // 是否有效 int frame_num; // 对应的物理页框号 } PageTableItem; // 一级页表 PageTableItem* page_table1[PAGE_NUM/2]; // 二级页表 PageTableItem* page_table2[PAGE_NUM/2][PAGE_NUM/2]; // 初始化页表 void init_page_table() { // 初始化一级页表 for (int i = 0; i < PAGE_NUM/2; i++) { page_table1[i] = NULL; } // 初始化二级页表 for (int i = 0; i < PAGE_NUM/2; i++) { for (int j = 0; j < PAGE_NUM/2; j++) { page_table2[i][j] = NULL; } } } // 映射虚拟地址到物理地址 int map_address(int virtual_address) { // 计算页号和页内偏移量 int page_num = virtual_address / PAGE_SIZE; int offset = virtual_address % PAGE_SIZE; // 计算页表项在一级页表二级页表中的索引 int idx1 = page_num / (PAGE_NUM/2); int idx2 = page_num % (PAGE_NUM/2); // 如果一级页表项为空,分配一个二级页表 if (page_table1[idx1] == NULL) { page_table1[idx1] = (PageTableItem*)malloc(sizeof(PageTableItem) * (PAGE_NUM/2)); for (int i = 0; i < PAGE_NUM/2; i++) { page_table1[idx1][i].valid = 0; } } // 如果二级页表项为空,分配一个物理页框 if (page_table2[idx1][idx2] == NULL) { for (int i = 0; i < FRAME_NUM/2; i++) { for (int j = 0; j < PAGE_NUM/2; j++) { if (page_table1[i][j].valid == 0) { page_table1[i][j].valid = 1; page_table1[i][j].frame_num = rand() % FRAME_NUM; page_table2[i][j] = (PageTableItem*)malloc(sizeof(PageTableItem) * (PAGE_NUM/2)); for (int k = 0; k < PAGE_NUM/2; k++) { page_table2[i][j][k].valid = 0; } break; } } } } // 获取物理地址 int physical_address = page_table1[idx1][idx2].frame_num * PAGE_SIZE + offset; return physical_address; } int main() { int virtual_address = 0x12345; // 十进制逻辑地址为74565 int physical_address = map_address(virtual_address); printf("虚拟地址 0x%x 被映射物理地址 0x%x\n", virtual_address, physical_address); return 0; } ``` 上述代码中,我们使用了一级页表二级页表来管理虚拟地址和物理地址映射关系。其中,一级页表中的每个页表项对应一个二级页表二级页表中的每个页表项对应一个物理页框。在进行地址映射时,首先计算页号和页内偏移量,然后根据页号在一级页表二级页表中查找对应的页表项。如果一级页表项为空,说明该虚拟页还没有被映射到物理页框上,我们需要分配一个二级页表,并在一级页表中更新对应的页表项。如果二级页表项为空,说明该虚拟页对应的物理页框还没有被分配,我们需要在物理内存中分配一个空闲页框,并在一级页表二级页表中更新对应的页表项。最后,根据页表项中的物理页框号和页内偏移量计算出物理地址,并返回给调用者。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值