根据gfp_mask来获得对应的zone

本篇文章只是分析一下gfp_mask到zone的对应关系在内核中的实现:

内核代码如下:(3.0) 

#define GFP_ZONE_TABLE	(ZONE_NORMAL << 0 * ZONES_SHIFT)				      \
	| (OPT_ZONE_DMA << ___GFP_DMA * ZONES_SHIFT)			      \
	| (OPT_ZONE_HIGHMEM << ___GFP_HIGHMEM * ZONES_SHIFT)		      \
	| (OPT_ZONE_DMA32 << ___GFP_DMA32 * ZONES_SHIFT)		      \
	| (ZONE_NORMAL << ___GFP_MOVABLE * ZONES_SHIFT)			      \
	| (OPT_ZONE_DMA << (___GFP_MOVABLE | ___GFP_DMA) * ZONES_SHIFT)	      \
	| (ZONE_MOVABLE << (___GFP_MOVABLE | ___GFP_HIGHMEM) * ZONES_SHIFT)   \
	| (OPT_ZONE_DMA32 << (___GFP_MOVABLE | ___GFP_DMA32) * ZONES_SHIFT)   \
)

static inline enum zone_type gfp_zone(gfp_t flags)
{
	enum zone_type z;
	int bit = (__force int) (flags & GFP_ZONEMASK);

	z = (GFP_ZONE_TABLE >> (bit * ZONES_SHIFT)) &
					 ((1 << ZONES_SHIFT) - 1);
	VM_BUG_ON((GFP_ZONE_BAD >> bit) & 1);
	return z;
}

分析一下gfp_zone函数,首先系统中的ZONE的个数,不超过2的ZONE_SHIFT次方,即可以用ZONE_SHIFT个BIT位来表示ZONE的值,

GFP_ZONEMASK定义的地方如下:

#define GFP_ZONEMASK	(__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE)

flags&GFP_ZONEMASK,是将与GFP_XXX无关的其他位清零,下面看一下GFP_ZONE_TABLE的定义,定义中包含的几个宏变量,定义如下:

#ifdef CONFIG_HIGHMEM
#define OPT_ZONE_HIGHMEM ZONE_HIGHMEM
#else
#define OPT_ZONE_HIGHMEM ZONE_NORMAL
#endif

#ifdef CONFIG_ZONE_DMA
#define OPT_ZONE_DMA ZONE_DMA
#else
#define OPT_ZONE_DMA ZONE_NORMAL
#endif

#ifdef CONFIG_ZONE_DMA32
#define OPT_ZONE_DMA32 ZONE_DMA32
#else
#define OPT_ZONE_DMA32 ZONE_NORMAL
#endif

从其定义可以看出,如果没有定义HIGHMEM,则ZONE_HIGHMEM自动指向ZONE_NORMAL,其他类似。GFP_ZONE_TABLE的定义,其实是将各个ZONE的值放到对应的BIT位上,ZONE_NORMAL放到[0,ZONE_SHIFT)位,GFP_DMA放到[ZONE_SHIFT, 2*ZONE_SHIFT)位上,依此类推。

知道了GFP_ZONE_TABLE的意义,下面的语句也就不难理解了,bit*ZONE_SHIFT即得到该ZONE所对应的BIT位,然后将GFP_ZONE_TABLE左移所得位数量,这时候得到的是从这个ZONE开始往上的所有BIT位,要将无关的ZONE清零,即只取低ZONE_SHIFT位,所以要&((1<<ZONE_SHITF) -1)。下面VM_BUG_ON内的语句只是做一下校验,读者可以自行分析一下,应该不难理解。



你可能感兴趣的:(table)