前面已经分析了内存管理框架的构建实现过程,有部分内容未完全呈现出来,这里主要做个补充。
如下图,这是前面已经看到过的linux物理内存管理框架的层次关系。
现着重分析一下各个管理结构体的成员功能作用。
【file:/include/linux/mmzone.h】
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_MEMCG
struct page_cgroup *node_page_cgroup;
#endif
#endif
#ifndef CONFIG_NO_BOOTMEM
struct bootmem_data *bdata;
#endif
#ifdef CONFIG_MEMORY_HOTPLUG
/*
* Must be held any time you expect node_start_pfn, node_present_pages
* or node_spanned_pages stay constant. Holding this will also
* guarantee that any pfn_valid() stays that way.
*
* pgdat_resize_lock() and pgdat_resize_unlock() are provided to
* manipulate node_size_lock without checking for CONFIG_MEMORY_HOTPLUG.
*
* Nests above zone->lock and zone->span_seqlock
*/
spinlock_t node_size_lock;
#endif
unsigned long node_start_pfn;
unsigned long node_present_pages; /* total number of physical pages */
unsigned long node_spanned_pages; /* total size of physical page
range, including holes */
int node_id;
nodemask_t reclaim_nodes; /* Nodes allowed to reclaim from */
wait_queue_head_t kswapd_wait;
wait_queue_head_t pfmemalloc_wait;
struct task_struct *kswapd; /* Protected by lock_memory_hotplug() */
int kswapd_max_order;
enum zone_type classzone_idx;
#ifdef CONFIG_NUMA_BALANCING
/* Lock serializing the migrate rate limiting window */
spinlock_t numabalancing_migrate_lock;
/* Rate limiting time interval */
unsigned long numabalancing_migrate_next_window;
/* Number of pages migrated during the rate limiting time interval */
unsigned long numabalancing_migrate_nr_pages;
#endif
} pg_data_t;
- struct zone node_zones[MAX_NR_ZONES];
——存放该pg_data_t里面的zone;
- struct zonelist node_zonelists[MAX_ZONELISTS];
——其指向一个page结构的数组,数组中的每个成员为该节点中的一个物理页面,于是整个数组就对应了该节点中所有的物理页面;
- struct page_cgroup *node_page_cgroup;
——用于管理page_cgroup,原来的page_cgroup是page页面管理结构的一个成员,现在移到这里了,它将会在初始化时所有的page_cgroup都将申请下来;
- struct bootmem_data *bdata;
——该数据指向bootmem_node_data,可以通过system.map查到。原是用于bootmem内存分配器的信息存储,当前改用memblock算法,则不存在该成员;
- unsigned long node_start_pfn;
——指向当前pg_data_t结构管理的物理起始页面;
- unsigned long node_present_pages;
——记录物理页面数总量,除开内存空洞的物理页面数;
- unsigned long node_spanned_pages;
——最大和最小页面号的差值,包括内存空洞的总的物理页面大小;
- int node_id;
——pg_data_t对应的索引号,非NUMA架构下该值为0;
- nodemask_t reclaim_nodes;
——用于记录可回收的内存管理节点node信息;
- wait_queue_head_t kswapd_wait;
——kswapd是页面交换守护线程,该线程会阻塞在这个等待队列,当满足条件后,调用wake_up_interruptible()唤醒该队列进行相关操作;
- wait_queue_head_t pfmemalloc_wait;
——用于减缓内存直接回收;
- struct task_struct *kswapd;
——指向kswapd守护线程的任务指针;
- int kswapd_max_order;
——用于表示kswapd守护线程每次回收的页面个数;
- enum zone_type classzone_idx;
——该成员与kswapd有关;
【file:/include/linux/mmzone.h】
struct zone {
/* Fields commonly accessed by the page allocator */
/* zone watermarks, access with *_wmark_pages(zone) macros */
unsigned long watermark[NR_WMARK];
/*
* When free pages are below this point, additional steps are taken
* when reading the number of free pages to avoid per-cpu counter
* drift allowing watermarks to be breached
*/
unsigned long percpu_drift_mark;
/*
* We don't know if the memory that we're going to allocate will be freea