Linux中内存管理详解_张孟浩_jay的博客-CSDN博客_linux内存管理
Linux的内存管理是什么,Linux的内存管理详解-电子发烧友网
上图的箭头代表总线,对于UMA(一致性内存访问,Uniform Memory Access),所以cpu都是通过同一根总线访问内存,当cpu和内存过多的时候,总线会成为性能瓶颈。
而NUMA(非一致性内存访问,None Uniform Memory Access)则是各个cpu访问自己的内存节点是通过各自的总线访问。节点之前的内存访问速度,虽然也会很慢,但可以尽量减少节点之间的内存访问。这样就能使得系统总的内存访问速度加快。
UMA模型是指物理内存是连续的,SMP系统中的每个处理器访问各个内存区都是同样快的;而NUMA模型则是指SMP中的每个CPU都有自己的物理内存区,虽然CPU可以访问其他CPU的内存区,但是要比方位自己的内存区慢得多.
物理内存组织
linux中内存分为3个级别。
1、Page:一个页的大小一般为4k,page是内存管理最基本的单位
2、Zone:分为ZONE_DMA,ZONE_NORMAL,ZONE_HIGHMEM
3、node节点:是对于NUMA的smp系统的,每个cpu都有自己的node,每个node里面又被分为了很多内存域zone,即ZONE_DMA,ZONE_NORMAL,ZONE_HIGHMEM等。对于UMA,系统中只有一个node
内存节点描述符的定义
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;//只struct page数组中第一个page,被放置到了全局数组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
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;
wait_queue_head_t kswapd_wait;
wait_queue_head_t pfmemalloc_wait;
struct task_struct *kswapd; /* Protected by
mem_hotplug_begin/end() */
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;
内存区域zone的定义
struct zone {
............................................
struct free_area free_area[MAX_ORDER];
..........................................
/*
* Discontig memory support fields.
*/
struct pglist_data *zone_pgdat;
/* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
unsigned long zone_start_pfn;
..................................................
} ____cacheline_internodealigned_in_smp;
struct free_area {
struct list_head free_list[MIGRATE_TYPES];
unsigned long nr_free;
};
./arch/alpha/mm/numa.c:22:pg_data_t node_data[MAX_NUMNODES];
在arm架构下,没有这个定义。是因为arm并不是NUMA架构??
对应UMA,内核会定义唯一内存节点contig_page_data
我这个是在linux-3.16\mm\nobootmem.c定义
#ifndef CONFIG_NEED_MULTIPLE_NODES
struct pglist_data __refdata contig_page_data;
EXPORT_SYMBOL(contig_page_data);
#endif
以下内容摘抄自深入理解linux虚拟内存管理(内核版本比较老,上面是linux3.16)
大型机器会将内存分为许多节点,根据节点与处理器"距离"的不同,访问不同的节点会有不同的代价。linux使用struct pglist_data 表示节点(书上说这个结构是一个链表,但是在3.16上,对于NUMA系统,是用一个数组来表示所有节点)。每个节点被分为很多的管理区块,zone。zone的类型一般都是ZONE_DMA,ZONENORMAL和ZONE_HIGHMEM。ZONE_DMA指低端范围的物理内存,是因为某些硬件只能访问最开始的一段物理内存,才诞生了zone_dma。zone_normal部分的内存由内核直接经过线性映射到内核地址空间的最开始的896M部分。zone_highmem是系统预留的可用空间,不可被内核直接映射,需要动态映射。
系统内存最终是被划分为了page,所有的page都存储在一个全局mem_map数组中。通过下图,我最开始以为,一个zone就会有一个mem_map数组。但是书上说该数组是全局变量。难道数组里面包含了系统里面所以的物理内存,部分page属于zone_dma,部分是zone_normal???