gfp_mask轉換成對應的zone
在分配記憶體時,都會帶分配引數比如GPF_KERNEL等等,那麼,一次記憶體分配從哪個zone分配了?
這裡就必需把mask轉換成zone,gfp_mask低4位用於表示分配的zone
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; }
其中ZONES_SHIFT,表示系統中的zone個數不超過2的ZONE_SHIFT次方,比如zone個數為5,那麼zone_SHIFT=3,用
3bit表示zone的index(0-5),如果只有三個zone,那麼ZONES_SHIFT=2,因為2個bit,可以表示4個數.
GFP_ZONEMASK定義的地方如下: #define GFP_ZONEMASK (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE)
#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)位上,依此類推。
bit*ZONE_SHIFT即得到該ZONE所對應的BIT位,然後將GFP_ZONE_TABLE左移所得位數量,這時候得到的是從這個ZONE開始往上的所有BIT位,要將無關的ZONE清零,即只取低ZONE_SHIFT位,所以要&((1<<ZONE_SHITF) -1)