进程需要的连续的页面,通过alloc_pages来完成
该函数在mm/numa.c和mm/page_alloc.h中都有定义
NUMA和UMA分配内存的函数是不并存的,根据CONFIG_DISCONTIGMEM的勾选与否选择其中一个
1. NUMA的分配内存函数:
选择CONFIG_DISCONTIGMEM选项
被编译的条件是“不连续的存储空间”,而不是CONFIG_NUMA,但是CONFIG_NUMA会对程序造成影响
alloc_pages(int gfp_mask,unsigned long order)
gfp_mask:表示采用哪一种分配策略
order:申请2^order个页面
numa的alloc_pages的代码:
如果定义了NUMA,就需要获取
pgdat_list,并且需要遍历所有的pg_data_t节点
分配时轮流从各个节点开始,并希望各节点负载均衡
在每个节点上使用
alloc_pages_pgdat函数
1
==================== mm/numa.c 43 43 ====================
2
43 #ifdef CONFIG_DISCONTIGMEM
3
==================== mm/numa.c 91 128 ====================
4
91 /*
5
92 * This can be refined. Currently, tries to do round robin, instead
6
93 * should do concentratic circle search, starting from current node.
7
94 */
8
95 struct page * alloc_pages(int gfp_mask, unsigned long order)
9
96 {
10
97 struct page *ret = 0;
11
98 pg_data_t *start, *temp;
12
99 #ifndef CONFIG_NUMA
13
100 unsigned long flags;
14
101 static pg_data_t *next = 0;
15
102 #endif
16
103
17
104 if (order >= MAX_ORDER)
18
105 return NULL;
19
106 #ifdef CONFIG_NUMA
20
107 temp = NODE_DATA(numa_node_id());
21
108 #else
22
109 spin_lock_irqsave(&node_lock, flags);
23
110 if (!next) next = pgdat_list;
24
111 temp = next;
25
112 next = next->node_next;
26
113 spin_unlock_irqrestore(&node_lock, flags);
27
114 #endif
28
115 start = temp;
29
116 while (temp) {
30
117 if ((ret = alloc_pages_pgdat(temp, gfp_mask, order)))
31
118 return(ret);
32
119 temp = temp->node_next;
33
120 }
34
121 temp = pgdat_list;
35
122 while (temp != start) {
36
123 if ((ret = alloc_pages_pgdat(temp, gfp_mask, order)))
37
124 return(ret);
38
125 temp = temp->node_next;
39
126 }
40
127 return(0);
41
128 }
1.2 alloc_pages_pgdat函数:
NUMA和UMA机制下都使用了相同的函数,在UMA处在做详细介绍
gfp_mask相当于node_zonelists数组的下标
1
85 static struct page * alloc_pages_pgdat(pg_data_t *pgdat, int gfp_mask,
2
86 unsigned long order)
3
87 {
4
88 return __alloc_pages(pgdat->node_zonelists + gfp_mask, order);
5
89 }
2. UMA的分配内存函数: 不选择CONFIG_DISCONTIGMEM选项
该函数只有在CONFIG_DISCONTIGMEM无定义时才编译
很明显在UMA结构下
只有一个pg_data_t节点,也就是
contig_page_data,所以无序遍历
具体的内存分配过程由__alloc_pages()完成
1
343 #ifndef CONFIG_DISCONTIGMEM
2
344 static inline struct page * alloc_pages(int gfp_mask, unsigned long order)
3
345 {
4
346 /*
5
347 * Gets optimized away by the compiler.
6
348 */
7
349 if (order >= MAX_ORDER)
8
350 return NULL;
9
351 return __alloc_pages(contig_page_data.node_zonelists+(gfp_mask), order);
10
352 }