内存分配掩码(gfp 您所在的位置:网站首页 linux掩码英文 内存分配掩码(gfp

内存分配掩码(gfp

2023-12-02 09:10| 来源: 网络整理| 查看: 265

本文内容均基于内核版本Linux-v3.2.40。     先说说GFP吧,曾几何时,每次写代码遇到kmalloc、alloc_page时都会疑惑,到底是GFP_KERNEL还是GPF_KERNEL,一直搞不清楚,每次都要先搜个例子看看,到后来才知道,原来 GFP是get free page的缩写! 现在想想,都快要被以前的自己蠢哭了,^_^

    好了,切入正题,本文主要讲解内存分配中的分配掩码。分配掩码包括两部分,内存域修饰符(占低4位)和内存分配标志(从第5位开始),如下图所示:

1. 内存域修饰符     前面的文章已经介绍过内存域zone的几种类型:ZONE_DMA、ZONE_DMA32、ZONE_NORMAL、ZONE_HIGHMEM、ZONE_MOVABLE。与类型不同,内存域的修饰符只有___GFP_DMA、___GFP_HIGHMEM、___GFP_DMA32、___GFP_MOVABLE 4种,没有ZONE_NORMAL对应的修饰符,因为ZONE_NORMAL是默认的内存申请类型。如下所示,为内存域修饰符的定义:

#define ___GFP_DMA 0x01u #define ___GFP_HIGHMEM 0x02u #define ___GFP_DMA32 0x04u #define ___GFP_MOVABLE 0x08u 这里主要想说明的是,内存域修饰符与伙伴系统分配器扫描内存域的顺序的关系,如下所示:

2. 内存分配标志     除了内存域修饰符之外,分配掩码中还包含了大量的分配标志,如下所示:

#define __GFP_WAIT ((__force gfp_t)___GFP_WAIT) /* 内存分配的过程中可以被打断 */ #define __GFP_HIGH ((__force gfp_t)___GFP_HIGH) /* 请求分配非常紧急的内存,注意与__GFP_HIGHMEM的区分,__GPF_HIGHMEM指从高端内存域分配内存 */ #define __GFP_IO ((__force gfp_t)___GFP_IO) /* 内存分配的过程中可进行IO操作,也就是说分配过程中如果需要换出页,必须设置该标志,才能将换出的页写入磁盘 */ #define __GFP_FS ((__force gfp_t)___GFP_FS) /* 内存分配过程中可执行VFS操作,也就是可以调用VFS的接口 */ #define __GFP_COLD ((__force gfp_t)___GFP_COLD) /* 分配不在cpu高速缓存中的冷页 */ #define __GFP_NOWARN ((__force gfp_t)___GFP_NOWARN) /* 内存分配时不允许内核发出警告,极少使用 */ #define __GFP_REPEAT ((__force gfp_t)___GFP_REPEAT) /* 内存分配失败后,会进行重试,重试若干次后停止 */ #define __GFP_NOFAIL ((__force gfp_t)___GFP_NOFAIL) /* 内存分配失败后一直重试,直至成功 */ #define __GFP_NORETRY ((__force gfp_t)___GFP_NORETRY) /* 内存分配失败后,不进行重试 */ #define __GFP_COMP ((__force gfp_t)___GFP_COMP) /* 增加复合元数据 */ #define __GFP_ZERO ((__force gfp_t)___GFP_ZERO) /* 申请全部填充为0的page */ #define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC) /* 不使用紧急分配链表 */ #define __GFP_HARDWALL ((__force gfp_t)___GFP_HARDWALL) /* 只能在当前进程可运行的cpu关联的内存节点上分配内存,如果进程可在所有cpu上运行,该标志无意义 */ #define __GFP_THISNODE ((__force gfp_t)___GFP_THISNODE) /* 只能在当前节点上分配内存 */ #define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) /* 请求分配可回收的page */ #define __GFP_NOTRACK ((__force gfp_t)___GFP_NOTRACK) /* 不对分配的内存进行跟踪 */ #define __GFP_NO_KSWAPD ((__force gfp_t)___GFP_NO_KSWAPD) #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */ 由于这些标志几乎总是组合使用,内核中作了一些分组,包含了用于各种标准情形的适当标志,如下所示:

/* This equals 0, but use constants in case they ever change */ #define GFP_NOWAIT (GFP_ATOMIC & ~__GFP_HIGH) /* GFP_ATOMIC means both !wait (__GFP_WAIT not set) and use emergency pool */ #define GFP_ATOMIC (__GFP_HIGH) /* 表示申请内存非常紧急,不能睡眠,不能有IO和VFS操作 */ #define GFP_NOIO (__GFP_WAIT) #define GFP_NOFS (__GFP_WAIT | __GFP_IO) #define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS) /* 可以睡眠,可以有IO和VFS操作 */ #define GFP_TEMPORARY (__GFP_WAIT | __GFP_IO | __GFP_FS | \ __GFP_RECLAIMABLE) /* 以下三个用于为用户空间申请内存 */ #define GFP_USER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL) /* 可以睡眠,可以有IO和VFS操作,只能从进程可运行的node上分配内存 */ #define GFP_HIGHUSER (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_HARDWALL | __GFP_HIGHMEM) /* 优先从高端zone中分配内存 */ #define GFP_HIGHUSER_MOVABLE (__GFP_WAIT | __GFP_IO | __GFP_FS | \ __GFP_HARDWALL | __GFP_HIGHMEM | __GFP_MOVABLE) /* 申请可移动的内存 */ #define GFP_IOFS (__GFP_IO | __GFP_FS) #define GFP_TRANSHUGE (GFP_HIGHUSER_MOVABLE | __GFP_COMP | \ __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | \ __GFP_NO_KSWAPD) 3. 常见的几种内存分配场景及使用的标志     1) 缺页异常分配内存时:GFP_HIGHUSER | __GFP_ZERO | __GFP_MOVABLE   /* 分配可移动的page,并且将page清零 */         do_page_fault() -> handle_pte_fault() -> do_anonymous_page() -> alloc_zeroed_user_highpage_movable()     2) 文件映射分配内存时:GFP_HIGHUSER_MOVABLE   /*  分配可移动的page */          do_page_fault() ->  handle_pte_fault() ->  do_anonymous_page() ->  do_nonlinear_fault() -> __do_fault()     3) vmalloc分配内存时:GFP_KERNEL | __GFP_HIGHMEM   /* 优先从高端内存中分配 */         vmalloc() -> __vmalloc_node_flags(size, -1, GFP_KERNEL | __GFP_HIGHMEM)     以上就是与内存分配掩码相关的内容,如有错误欢迎指正。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有