首页 百科知识 物理内存的管理

物理内存的管理

时间:2022-10-09 百科知识 版权反馈
【摘要】:为了满足用户的需要,支持更多内存、提高性能,并建立一种独立于架构的内存描述方法,Linux内存模型将内存划分成分配给每个CPU的空间。PAE是Intel提供的内存地址扩展机制,它通过在宿主操作系统中使用Address Windowing Extensions API为应用程序提供支持,从而让处理器将可以用来寻址物理内存的位数从32位扩展为36位。这个物理内存区域的管理是通过一个区域分配器实现的。Linux对物理内存空间按照分页方式进行管理,把物理内存划分成大小相同的物理页面。

4.4 物理内存的管理

在32位架构上的Linux内核按照3:1的比率来划分虚拟内存:3GB的虚拟内存用于用户空间,1GB的内存用于内核空间。内核代码及其数据结构都必须位于这1GB的地址空间中。

为了满足用户的需要,支持更多内存、提高性能,并建立一种独立于架构的内存描述方法,Linux内存模型将内存划分成分配给每个CPU的空间。每个空间都称为一个节点;每个节点都被划分成一些区域。区域(表示内存中的范围)可以进一步划分为以下类型:

ZONE_DMA(0-16 MB):包含ISA/PCI设备需要的低端物理内存区域中的内存范围。

ZONE_NORMAL(16-896MB):由内核直接映射到高端范围的物理内存的内存范围。所有的内核操作都只能使用这个内存区域来进行,因此这是对性能至关重要的区域。

ZONE_HIGHMEM(896MB以及更高的内存):系统中内核不能映像到的其他可用内存。

节点的概念在内核中是使用struct pglist_data结构来实现的。区域是使用struct zone_struct结构来描述的。物理页框是使用struct page结构来表示的,所有这些struc都保存在全局结构数组struct mem_map中,这个数组存储在ZONE_NORMAL的开头。节点、区域和页框之间的基本关系如图4-6所示。

当实现了对Pentium II的虚拟内存扩展的支持(在32位系统上使用PAE——Physical Address Extension——可以访问64GB的内存)和对4GB的物理内存(同样是在32位系统上)的支持时,高端内存区域就会出现在内核内存管理中了。这是在I386和SPARC平台上引用的一个概念。通常这4GB的内存可以通过使用kmap()将ZONE_HIGHMEM映射到ZONE_NORMAL来进行访问。请注意在32位的架构上使用超过16GB的内存是不明智的,即使启用了PAE也是如此。

PAE是Intel提供的内存地址扩展机制,它通过在宿主操作系统中使用Address Windowing Extensions API为应用程序提供支持,从而让处理器将可以用来寻址物理内存的位数从32位扩展为36位。

这个物理内存区域的管理是通过一个区域分配器(zone allocator)实现的。它负责将内存划分为很多区域;它可以将每个区域作为一个分配单元使用。每个特定的分配请求都利用了一组区域,内核可以从这些位置按照从高到低的顺序来进行分配。

img19

图4.6 节点、区域和页框之间的关系

例如:

对于某个用户页面的请求可以首先从“普通”区域中来满足(ZONE_NORMAL);如果失败,就从ZONE_HIGHMEM开始尝试;如果这也失败了,就从ZONE_DMA开始尝试。

这种分配的区域列表依次包括ZONE_NORMAL、ZONE_HIGHMEM和ZONE_DMA区域。另一方面,对于DMA页的请求可能只能从DMA区域中得到满足,因此这种请求的区域列表就只包含DMA区域。

Linux对物理内存空间按照分页方式进行管理,把物理内存划分成大小相同的物理页面。在I386机器中一个页面的大小为4KB,定义在include/asm-i386/page.h文件中:

#define PAGE_SHIFT 12

#define PAGE_SIZE (1UL 〈〈 PAGE_SHIFT)

在Alpha、Sparc中一个页面大小8KB:

#define PAGE_SHIFT 13

#define PAGE_SIZE (1UL 〈〈 PAGE_SHIFT)

Linux设置了一个mem_map[]数组管理内存页面。

mem_map[]在系统初始化时由free_area_init()函数创建,它存放在物理内存的底部(低地址部分),mem_map[]数组的元素是一个个的page结构体,每一个page结构体它对应一个物理页面。page结构进一步被定义为mem_map_t类型,其定义在/include/linux/mm.h中:

typedef struct page { /* 物理页描述字 */

  struct page *next,*prev; /*把page结构体链成双向循环链表,这两项必须先定义*/

  struct inode *inode; /*若该页面的内容是文件,则是有关文件的inode*/

  unsigned long offset;/* 在文件中的偏移量*/

  struct page *next_hash,*prev_hash; /*把有关page结构体连成一个哈希表*/

  atomic_t count; /*访问此页面的进程计数,大于1表示由多个进程共享*/

  unsigned flags; /*页面标志*/

  unsigned dirty:16, /*表示该页面是否被修改过*/

      age:8; /*标志页面的“年龄”, 越小越先换出 */

  struct wait_queue *wait; /*是等待该页资源的进程等待队列的指针*/

  struct buffer_head * buffers; /* 若该页面作为缓冲区,则指示地址 */

  unsigned long swap_unlock_entry;

  unsigned long map_nr; /*该页面page结构体在mem_map[]数组中的下标值,*也就是物理页面的页号*/

} mem_map_t;

页面标志flags的含义见表4-2。

表4-2 page结构中页面标志flag的含义

img20

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈