Linux可以支持大量的架构,所以需要用一种与架构无关的方式去描述内存。在linux的内存管理中,我们首先要明确的一个概念就是NUMA(Non-Uniform Memory Access,关于NUMA的介绍可以参考我前面的文章)。很多大型机器都采用NUMA架构,将内存和CPU分为很多组,每一组称为一个节点(node)。节点与节点之间的互相访问,会因为“距离”的不同导致不同的开销。Linux通过struct pglist_data这个结构体来描述节点,对于UMA架构,Linux同样会保留节点的概念,只是整个系统就是一个节点,只需要一个struct pglist_data来描述,它叫作contig_page_data.
struct pglist_data结构描述如下,现在只需了解其中的关键项即可
-
????typedef struct pglist_data {
-
struct zone node_zones[MAX_NR_ZONES];
-
struct zonelist node_zonelists[MAX_ZONELISTS];
-
int nr_zones;
-
#ifdef CONFIG_FLAT_NODE_MEM_MAP /* means !SPARSEMEM */
-
struct page *node_mem_map;
-
#ifdef CONFIG_CGROUP_MEM_RES_CTLR
-
struct page_cgroup *node_page_cgroup;
-
#endif
-
#endif
-
struct bootmem_data *bdata;
-
#ifdef CONFIG_MEMORY_HOTPLUG
-
-
-
-
-
-
-
-
spinlock_t node_size_lock;
-
#endif
-
unsigned long node_start_pfn;
-
unsigned long node_present_pages;
-
unsigned long node_spanned_pages;
-
-
int node_id;
-
wait_queue_head_t kswapd_wait;
-
struct task_struct *kswapd;
-
int kswapd_max_order;
每个节点的内存会被分为几个块,我们称之为管理区(zone),对于一个管理区,我们使用struct zone结构体来描述。管理区的类型可以分为ZONE_NORMAL,ZONE_DMA,ZONE_HIGHMEM三种。这三个管理区在物理内存上的布局为
ZONE_DMA: 0~16MB
ZONE_NORMAL: 16MB~896MB
ZONE_HIGHMEM:896MB~end
struct zone结构描述如下:
物理内存中的每个页都会有一个与之关联的struct page结构来对其进行描述和跟踪,其结构描述如下
-
struct page {
-
unsigned long flags;
-
-
atomic_t _count;
-
union {
-
atomic_t _mapcount;
-
-
-
-
struct {
-
u16 inuse;
-
u16 objects;
-
};
-
};
-
union {
-
struct {
-
unsigned long private;
-
-
-
-
-
-
-
struct address_space *mapping;
-
-
-
-
-
-
-
};
-
#if USE_SPLIT_PTLOCKS
-
spinlock_t ptl;
-
#endif
-
struct kmem_cache *slab;
-
struct page *first_page;
-
};
-
union {
-
pgoff_t index;
-
void *freelist;
-
};
-
struct list_head lru;
-
-
-
-
-
-
-
-
-
-
-
-
-
#if defined(WANT_PAGE_VIRTUAL)
-
void *virtual;
-
-
#endif /* WANT_PAGE_VIRTUAL */
-
#ifdef CONFIG_WANT_PAGE_DEBUG_FLAGS
-
unsigned long debug_flags;
-
#endif
-
-
#ifdef CONFIG_KMEMCHECK
-
-
-
-
-
void *shadow;
-
#endif
-
};
Node,Zone和Page的关系可以用下图来描述
至此,已经对内存管理中的这三个关键数据结构有了一个感性的认识,在后面将会结合具体的代码来逐步深入,选择的代码版本为2.6.32.59~