上一篇
分页存储管理结构c
- 行业动态
- 2025-05-03
- 12
分页存储管理将内存划分为等大页框,逻辑地址分为页号与偏移,通过页表映射物理页,消除外碎片,提升内存利用率,但存在内碎片及页
分页存储管理结构详解
分页存储管理的基本概念
分页存储管理是操作系统内存管理的核心机制之一,通过将进程的逻辑地址空间划分为固定大小的页(Page),并将物理内存划分为相同大小的页框(Frame),实现逻辑地址到物理地址的映射,这种机制解决了连续内存分配的碎片问题,提升了内存利用率。
核心特点:
- 固定大小的页和页框:通常为4KB、2MB或更大(现代系统支持巨大页)。
- 逻辑地址分解:逻辑地址分为页号(Page Number)和页内偏移(Offset)。
- 页表映射:通过页表(Page Table)建立页号到页框的映射关系。
逻辑地址到物理地址的转换
分页系统中,逻辑地址的转换需要以下步骤:
分解逻辑地址:
- 逻辑地址 = 页号(高位) + 页内偏移(低位)。
- 逻辑地址
0x0040
(假设页大小为16字节):- 页号 =
0x0040 / 16 = 0x0004
(第4页) - 偏移 =
0x0040 % 16 = 0x0
(页内第0字节)
- 页号 =
查询页表:
- 页表是一个数组,索引为页号,值为对应的页框号。
- 页表项
PT[4] = 0x05
,表示第4页映射到第5号页框。
生成物理地址:
- 物理地址 = 页框号 × 页大小 + 偏移。
- 页框号
0x05
,偏移0x0
,则物理地址为0x0500
。
示例表格:
| 逻辑地址 | 页号 | 偏移 | 页框号 | 物理地址 |
|———-|——|——|——–|———-|
| 0x0040 | 4 | 0x0 | 0x05 | 0x0500 |
| 0x006A | 4 | 0xA | 0x05 | 0x050A |
页表结构与实现
页表是分页系统的核心数据结构,其设计直接影响内存访问效率。
基本页表:
- 每个进程维护一个独立页表,包含所有页的映射信息。
- 缺点:页表占用大量内存(32位系统需要4MB页表)。
多级页表(以二级为例):
- 将页表分为外页表和内页表,外页表存储内页表的物理地址。
- 优点:减少内存占用,支持稀疏地址空间。
- 示例:
- 逻辑地址分解为:外页号 + 内页号 + 偏移。
- 外页表项指向内页表,内页表项指向页框。
哈希页表:
- 使用哈希表替代数组,减少内存浪费。
- 适用场景:稀疏地址空间或超大页系统。
页面置换算法(C语言实现)
当物理内存不足时,需将内存中的页交换到磁盘(即缺页中断),并选择一个页替换出去,以下是常见算法的C语言实现思路:
FIFO(先进先出):
int pageQueue[MAX_FRAMES]; // 队列存储页框号 int queueHead = 0; void replacePageFIFO(int newPage) { int oldPage = pageQueue[queueHead]; pageQueue[queueHead] = newPage; queueHead = (queueHead + 1) % MAX_FRAMES; // 将oldPage对应的页写回磁盘 }
LRU(最近最少使用):
int pageAccessTime[MAX_FRAMES]; // 记录访问时间戳 void replacePageLRU(int newPage) { int oldestPage = 0; for (int i = 1; i < MAX_FRAMES; i++) { if (pageAccessTime[i] < pageAccessTime[oldestPage]) { oldestPage = i; } } // 替换oldestPage,更新新页的时间戳 }
分页存储的C语言模拟实现
以下是一个简单的分页系统模拟框架:
#define PAGE_SIZE 4096 // 4KB #define NUM_FRAMES 100 // 物理页框数 #define PAGE_TABLE_SIZE 1024 // 逻辑页数 typedef struct { int frameNumber; // 页框号 int valid; // 有效位(标记是否在内存中) } PageTableEntry; PageTableEntry pageTable[PAGE_TABLE_SIZE]; int memoryFrames[NUM_FRAMES]; // 存储当前加载的页框 int nextFreeFrame = 0; // 下一个空闲页框 // 逻辑地址转换函数 int translateAddress(unsigned int logicalAddress) { int pageNum = logicalAddress / PAGE_SIZE; int offset = logicalAddress % PAGE_SIZE; if (pageNum >= PAGE_TABLE_SIZE || !pageTable[pageNum].valid) { // 缺页中断处理(如调用页面置换算法) return -1; // 错误标志 } int frameNum = pageTable[pageNum].frameNumber; return frameNum PAGE_SIZE + offset; // 物理地址 }
分页存储的优化策略
TLB(快表)加速:
- TLB是页表的缓存,存储最近使用的页表项。
- 命中率优化:增大TLB容量或采用多级TLB。
反向页表:
- 按物理页框存储映射关系,减少内存占用。
- 适用场景:超大规模内存系统。
巨大页支持:
- 支持2MB、1GB等超大页面,减少页表项数量。
- 优势:降低TLB缺失率,提升性能。
FAQs
Q1:分页存储管理与分段存储管理的区别是什么?
A1:分页和分段是两种不同的内存管理方式:
- 分页:逻辑地址按固定大小划分,无需对齐,无外部碎片但可能有内部碎片。
- 分段:按程序逻辑单元划分(如函数、数组),段大小不固定,无内部碎片但可能有外部碎片。
- 本质区别:分页面向硬件(提高效率),分段面向程序逻辑(提高可读性)。
Q2:如何选择页面置换算法?
A2:选择算法需综合考虑场景和性能需求:
- FIFO:实现简单,但可能替换常用页(Belady异常)。
- LRU:接近理想算法,但需要记录访问顺序(开销大)。
- LFU:适合访问频率差异大的场景,但可能忽略时间局部性。
- 实际策略:现代系统常结合多种算法(如LRU-K、Clock算法)或使用