zones
linux内存管理区
因为硬件的限制,linux内核没有把所有的物理页面归做一类。由于有些页面的的内存物理地址不能够用作一些任务,linux内核把物理页面划分为3个不同的管理区。linux内核安页面拥有不同的属性来进行分类。特别地,linux必须处理内存地址对应的两个硬件缺陷:
- 一些硬件设备只能够在一些特定的物理地址执行DMA(直接内存传送)操作
- 一些处理器架构能够比实际映射更多的物理地址,由此导致一些内存不能够永久地映射到内核地址空间
由于以上的种种限制,linux把物理内存划分为以下三种管理区:
- ZONE_DMA 包含能够执行DMA操作的物理页面
- ZONE_NORMAL 包含常规地址映射的物理页面
- ZONE_HIGHMEM 包含高端地址的物理页面,不可以永久映射到linux内核地址空间
这些管理区在头文件linux/mmzone.h中定义
内存管理区实际的使用和布局是架构独立的。例如,一些处理器架构在任务物理地址都可以执行DMA操作。在这些处理器中,ZONE_DMA是空的并且ZONE_NORMAL可以任意使用而不用管其用途。相反,在x86处理器架构中,ISA设备不能够在全32为地址空间执行DMA操作,因为ISA设备只能够读取16MB的物理地址。所以在x86上的ZONE_DMA由物理地址0~16MB区间构成。
ZONE_HIGHMEM和ZONE_NORMAL一样根据处理器架构的不同而不同。在x86上,ZONE_HEIGMEM在物理地址>896MB的区间。在其他的架构上,ZONE_HIGHMEM是空的因为所有内存是直接映射的。在ZONE_HIGHMEM中的物理地址叫做高端地址,剩下地址叫做低端地址。
ZONE_NORMAL更趋向定义为前两个内存管理区划分后的剩下的内存空间。譬如在x86上,ZONE_NORMAL的物理内存区间划分在16MB~896MB。其他的处理去架构则是所有可用的内存。下表列出了在x86上每个管理区的物理页分配情况。
| ZONE | Description | Physical Memory |
|---|---|---|
| ZONE_DMA | DMA-able pages | < 16MB |
| ZONE_NORMAL | Normally addressable pages | 16896MB |
| ZONE_HIGHMEM | Dynamically mapped pages | >896MB |
linux把系统页面划分为不同的管理区来用池的管理概念按需求分配页面。譬如ZONE_DMA管理区赋予了内核满足DMA功能的内存分配能力。如果有这样的内存需求,内核就简单地从ZONE_DMA把请求的页面数分配出去即可。需注意的是管理区没有任何的内存物理相关性质依赖,它们仅仅是linux内核用来追踪页面的一种逻辑分类。
虽然一些应用可能需要指定管理区的页面,在一些应用中,管理区的指定并非是强制性的。虽然对可以执行DMA操作的内存分配必须来自ZONE_DMA,但是低端的内存分配可以来自ZONE_DMA和ZONE_NORMAL。当然,linux内核更喜欢把ZONE_NORMAL区中的页面分配给低端需求,分配ZONE_DMA管理区的内存分配给直接传送的应用。但是如果分配过于频繁,实际上应该分配自低端区的空间,linux内核将会不区分管理区。
在linux/mmzone.h中用struct zone定义管理区:
|
|
zone结构体很是大,但是系统中只有3种管理区,所以只有三个这样的结构体,下面让我们分析一些重要的字段:
lock字段是一个自旋锁,用来保护结构在多线程并发获取时引起的问题。需要注意的是自旋锁自保护这个管理区结构体,而非在这个管理区的页面。虽然内核的部分可能锁定保护在管理区页面的数据,但是没有明确的锁保护个别物理页面。
free_pages字段是一个管理区中可用的物理页面数量,如果可能的话,内核尽可能地至少保持有pages_min个空闲页面。
name字段毫无疑问是一个管理区的以NULL结尾的字符串名字。内核在引导期间(mm/page_alloc.c)初始化管理区的名字,同时三个管理区分别命名为”DMA”,”Normal”和”HighMem”。
