页表

1. 虚拟和物理地址空间

每个进程的内存地址空间在大多数情况下要比系统中可用的物理内存要大。内核要考虑将实际内存划分给进程需要的地址空间,最可取的一个方法就是加一个页表。页表来为物理地址分配虚拟地址,进程的地址空间则用虚拟地址表示。如下图所示,不同进程的同一个虚拟地址可能会映射到同一个物理内存页(通常称为页帧)上,它们的含义是不同的。

 

2. 页表

页表的作用就是将虚拟地址空间映射到物理地址空间。那么最容易让人想到的办法就是使用一个数组,但在实际应用中最普遍的是多级分页。

2.1 数组页表

在虚拟地址空间的每一页都有一个数组项对应。那么如果虚拟地址空间为4GB,页表为4KB的话,就需要2^20项即1M项,如果每个项目是4B,那每个进程光页表就是4M,如果同时有100个进程在运行,那就消耗了400M内存。而实际上,很多页表项是标记为用不到的,所以这就造成了很大资源浪费。

2.2 多级页表

前面的数组页表,我们可以理解为一级页表,很多时候大家也都称之为线性寻址。 我们试想下用二级页表,能不能解决上面的问题。我们将原先的页表一分为二,页表项(10位)+偏移地址(10位)。还是上面的例子,不过我们这里的页表项可以索引到2^10*4KB大小物理地址,然后在通过偏移地址索引到具体的物理页帧。那我们计算下空间消耗,页表项2^10共1024项,如果有效页表项为64个,那么总的内存消耗就是1088*4B,约4KB。同理,在地址空间允许的范围内,分级越多,消耗的内存越小。但也并不是越多越好,毕竟逐级访问也是要消耗时间的。

一般来讲在IA-32的CPU上,使用两级页表就够了。但到64位体系结构上,由于地址空间比较大,就需要三级或四级的页表了。只要懂了上面二级页表的例子,多级页表的也很容易懂。如下图

 

3. 多级页表加速

多级页表可以节省大量空间,但缺点也显而易见,那就是要逐级多次访问数组才能拿到物理地址。CPU通过以下方法来加快这个寻址的过程。

  • MMU(Memory Management Unit, 内存管理单元)
  • TLB (Translation Lookaside Buffer, TLB) 地址转换后备缓冲器,这个缓冲器中保存地址转换最为频繁的地址。

注意这两个不是并列的,MMU是CPU中一种硬件,虚拟地址到物理地址空间的转换这部分工作正式它来做的,TLB则是MMU内部的一个小而且高速的存储器。当然MMU另一个重要的作用就是保护内存地址空间。

 

 

参考:

[1] https://baike.baidu.com/item/MMU/4542218?fr=aladdin

[2] 深入Linux内核架构

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
页表是操作系统中用来记录虚拟内存地址与物理内存地址映射关系的数据结构,其实现方式因操作系统不同而异。以下是一个简单的页表代码实现示例,供参考: ```c #define PAGE_SIZE 4096 // 页大小为 4KB #define PAGE_NUM 1024 // 页表项数为 1024 struct page_table_entry { unsigned int present : 1; // 页是否存在 unsigned int writeable : 1; // 页是否可写 unsigned int user_access : 1; // 用户是否有访问权限 unsigned int write_through : 1; // 是否写直达 unsigned int cache_disabled : 1; // 是否禁用缓存 unsigned int accessed : 1; // 是否被访问过 unsigned int dirty : 1; // 是否被修改过 unsigned int zero : 1; // 保留位 unsigned int global : 1; // 全局页标志位 unsigned int available : 3; // 空闲可用位 unsigned int page_frame : 20; // 物理页框号 }; struct page_table_entry page_table[PAGE_NUM]; // 初始化页表 // 将虚拟地址映射到物理地址 void map_virtual_to_physical(unsigned int virtual_address, unsigned int physical_address) { unsigned int page_index = virtual_address / PAGE_SIZE; // 计算页号 page_table[page_index].present = 1; // 设置页存在 page_table[page_index].writeable = 1; // 设置页可写 page_table[page_index].user_access = 1; // 设置用户可访问 page_table[page_index].write_through = 0; // 不写直达 page_table[page_index].cache_disabled = 0; // 不禁用缓存 page_table[page_index].accessed = 0; // 未被访问过 page_table[page_index].dirty = 0; // 未被修改过 page_table[page_index].zero = 0; // 保留位清零 page_table[page_index].global = 0; // 非全局页 page_table[page_index].available = 0; // 空闲可用位清零 page_table[page_index].page_frame = physical_address / PAGE_SIZE; // 计算页框号 } ``` 以上代码实现了将虚拟地址映射到物理地址的功能,具体实现方式可能会因操作系统的不同而有所差异。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值