尘 2012-11-19 21:07
#ifdef CONFIG_FLAT_NODE_MEM_MAP /* means !SPARSEMEM */
struct page *node_mem_map;指向页结构的数组,该数组包含了节点中所有域的页
......
#ifndef CONFIG_NO_BOOTMEM
系统启动时会启用一套临时内存管理机制,struct bootmem_data就是该机制的管理结构
struct bootmem_data *bdata;
#endif
......
node_start_pfn表示节点中第一个页帧编号。页帧的编号是全局统一的,在UMA系统中只有一个节点所以node_start_pfn为0.
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; 指向负责该结点的交换进程的task_struct 结构
int kswapd_max_order; 由页交换子系统使用,定义要释放的区域大小。
enum zone_type classzone_idx;
} pg_data_t;
1.2 内存域
系统中所有内存域类型由一个枚举结构来管理:
include/linux/mmzone.h
enum zone_type {
#ifdef CONFIG_ZONE_DMA
ZONE_DMA, 适用于DMA的内存域
#endif
#ifdef CONFIG_ZONE_DMA32
使用32位寻址的适用于DMA的内存域,只有在64为系统中才与ZONE_DMA有差别
ZONE_DMA32,
#endif
ZONE_NORMAL,可直接映射到内核段的普通内存域
#ifdef CONFIG_HIGHMEM
ZONE_HIGHMEM,超出了内核段的物理内存
#endif
ZONE_MOVABLE,伪内存域,防止物理内存碎片机制中要使用该内存域
__MAX_NR_ZONES 可能有的内存域的总数
};
内存域管理结构struct zone在文件include/linux/mmzone.h中定义,如下:
struct zone {
数组watermark管理该内存域的三个水线值:
WMARK_HIGH:空闲页多余该值表示内存域的状态是理想的
WMARK_LOW:空闲页低于该值,内核开始将页换出到磁盘
WMARK_MIN:空闲页低于该值,急需空闲页,内存紧张
unsigned long watermark[NR_WMARK];
当空闲页低于该值,采取一些方法计算空闲页的总数,避免内存漂移导致水线值失效
unsigned long percpu_drift_mark;
保留一些空闲页,用于一些无论如何都不会失败的关键性分配
unsigned long lowmem_reserve[MAX_NR_ZONES];
unsigned long dirty_balance_reserve;
#ifdef CONFIG_NUMA
int node; 所属的NUMA节点
当可回收的页超过此值时,将进行页面回收。
unsigned long min_unmapped_pages;当
内存管理区中,用于slab的可回收页大于此值时,将回收slab中的缓存页。
unsigned long min_slab_pages;
#endif
每CPU的页面缓存, 当分配单个页面时,首先从该缓存中分配页面,可提高效率
struct per_cpu_pageset __percpu *pageset;
该锁用于保护伙伴系统数据结构。即保护free_area相关数据。
spinlock_t lock;
当管理区中的所有页面都不可回收时设置此标志
int all_unreclaimable;
......
用于实现伙伴系统。这个数组定义了11个队列,每个队列中的元素都是大小为2^n的页面块。
struct free_area free_area[MAX_ORDER];
......
#ifdef CONFIG_COMPACTION
下面字段用于内存紧缩。
unsigned int compact_considered;
unsigned int compact_defer_shift;
int compact_order_failed;
#endif
ZONE_PADDING(_pad1_)确保后面的字段是缓存行对齐的
下面几个字段都跟页面回收相关
spinlock_t lru_lock;
struct lruvec lruvec;
unsigned long pages_scanned; /* since last reclaim */
unsigned long flags; /* zone flags, see below */
该内存区域中的各种统计信息,
atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
unsigned int inactive_ratio;
ZONE_PADDING(_pad2_)
等待队列,用于等待该区域内存的进程
wait_queue_head_t * wait_table;
unsigned long wait_table_hash_nr_entries;
unsigned long wait_table_bits;
struct pglist_data *zone_pgdat;指向该区域所属的结点
unsigned long zone_start_pfn;该区域的起始页帧号
unsigned long spanned_pages; 该区中包含空洞在内,总的页帧数
unsigned long present_pages; 总的页帧数,不包含空洞
const char *name;该区域的名字,如Normal、DMA、Highmem等
} ____cacheline_internodealigned_in_smp;
1.3 页面
系统中每个物理页面都有一个相关联的page结构用于记录该页面的状态
include/linux/mm_types.h
struct page {
页面标志,也包含了一些其他信息,比如页面所处的管理区编号等
unsigned long flags;
如果最低位为0,则指向inode 的address_space,或则为NULL。如果页映射为匿名内存,最低位置位,而且该指针指向anon_vma对象
struct address_space *mapping;
......
struct {
union {
表示在也表中有多少项指向该页
atomic_t _mapcount;
用于slub
struct {
unsigned inuse:16;
unsigned objects:15;
unsigned frozen:1;
};
};
页的使用计数
atomic_t _count;
};
};
};
......
union {
指向私有数据的指针,虚拟内存管理会忽略该数据。根据页的用途,可以用不同的方式使用该指针。
unsigned long private;
......
用于SLUB分配器,指向slab的指针
struct kmem_cache *slab;
用于复合页,指向首页
struct page *first_page;
};
用于高端内存区中的页,即无法直接映射到内核内存中的页。Virtual用于存储该页的虚拟地址。
void *virtual;
......