伙伴系统分配器 分配掩码

kernel伙伴系统分配的函数,只能分配2的整数幂个页,更细力度的分配只能借助与slab或者slub分配器

常见的分配函数是:

alloc_pages(mask, order)

分配2的order幂次个页面,如果成功返回第一个页框对应的page结构,失败则返回NULL

get_zeroed_page(mask)

分配一个页面,成功则返回这个页框对应的page结构,失败返回NULL,要求返回页面的内容为全0

get_dma_pages(gfp_mask, order)

用于获得适合DMA操作的2的order幂次个页面


在上面的两个函数中,都强制使用了gfp_mask参数,该参数指定了分配的域修饰符以及一些额外的标志

域修饰符

掩码的最低3位为域修饰符,用来描述从哪个域分配页面。

/*
 * GFP bitmasks..
 *
 * Zone modifiers (see linux/mmzone.h - low three bits)
 *
 * Do not put any conditional on these. If necessary modify the definitions
 * without the underscores and use the consistently. The definitions here may
 * be used in bit comparisons.
 */
#define __GFP_DMA       ((__force gfp_t)0x01u)
#define __GFP_HIGHMEM   ((__force gfp_t)0x02u)
#define __GFP_DMA32     ((__force gfp_t)0x04u)

GFP 是 Get free pages的缩写

当域修饰符为__GFP_DMA时,表示分配只能发生在DMA zone,如果DMA zone分配失败,由于DMA zone是高级的Zone,那么kernel不会再尝试从Normal zone或者Highmem zone进行分配,这也是符合DMA操作特点的,因为有些DMA控制器无法操作大于16MB的地址空间。

当修饰符为__GFP_HIGHMEM时,表示优先从Highmem进行分配,如果分配失败,则会从Normal zone尝试分配,如果还失败,那么就使用DMA zone来分配,虽然这种方法可以尽量满足Highmem的分配请求,但是却使得不重要的分配请求,占用了重要的内存空间。从而导致后续的Normal zone或者DMA zone的分配失败。实际上我们可以通过修改zone_lists或者lowmem_reserved来限制低级分配请求占用高级内存域。

当修饰符为0时,表示缺省从Normal zone进行分配,如果分配失败,则会尝试从DMA zone进行分配。


操作修饰符

和域修饰符相反,操作修饰符不会限制从哪个内存分配页面,但是却影响着分配器的行为。

#define __GFP_WAIT      ((__force gfp_t)0x10u)  /* Can wait and reschedule? */
#define __GFP_HIGH      ((__force gfp_t)0x20u)  /* Should access emergency pools? */
#define __GFP_IO        ((__force gfp_t)0x40u)  /* Can start physical IO? */
#define __GFP_FS        ((__force gfp_t)0x80u)  /* Can call down to low-level FS? */
#define __GFP_COLD      ((__force gfp_t)0x100u) /* Cache-cold page required */
#define __GFP_NOWARN    ((__force gfp_t)0x200u) /* Suppress page allocation failure warning */
#define __GFP_REPEAT    ((__force gfp_t)0x400u) /* Retry the allocation.  Might fail */
#define __GFP_NOFAIL    ((__force gfp_t)0x800u) /* Retry for ever.  Cannot fail */
#define __GFP_NORETRY   ((__force gfp_t)0x1000u)/* Do not retry.  Might fail */
#define __GFP_COMP      ((__force gfp_t)0x4000u)/* Add compound page metadata */
#define __GFP_ZERO      ((__force gfp_t)0x8000u)/* Return zeroed page on success */
#define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
#define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
#define __GFP_THISNODE  ((__force gfp_t)0x40000u)/* No fallback, no policies */
#define __GFP_RECLAIMABLE ((__force gfp_t)0x80000u) /* Page is reclaimable */
#define __GFP_MOVABLE   ((__force gfp_t)0x100000u)  /* Page is movable */

__GFP_WAIT表示分配内存的请求可以被中断,也就是说在分配期间,调度器可以选择另外一个进程执行。或者该请求可以被另外的事件中断。分配器还可以在返回前,在队列上等待另外一个事件(相关进程进入休眠状态)

__GFP_HIGH 表示内核急切需要内存,系统分配内存会带了严重后果。由于__GFP_HIGH又等于GFP_ATOMIC,意味着__GFP_HIGH禁止中断,并且可以使用紧急分配链表的内存。

__GFP_IO 表示在查找空闲内存期间,内核可以执行IO操作,这意味着,如果没有足够的内存,那么当设置此标志时,允许回收系统把选择的页写回磁盘。

__GFP_FS 允许执行低层文件系统操作

__GFP_COLD 如果需要分配不在CPU高速缓存中的冷页面时,则设置__GFP_COLD

__GFP_NOWARN 在内核分配内存失败时,禁止内核故障警告。

__GFP_REPEAT 在分配失败后继续尝试,但在若干次后停止尝试。

__GFP_ZERO 分配成功后,把所有返回的页填充0

__GFP_NOMEMALLOC  不允许使用紧急预留内存。

__GFP_THISNODE 只有在NUMA系统上才有意义,如果置位,那么在分配失败的情况下,不允许尝试其他节点。

__GFP_RECLAIMABLE和__GFP_MOVABLE 标记从哪个空闲链表获取内存。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值