设为首页 加入收藏

TOP

kmalloc分配物理内存与高端内存映射--Linux内存管理(十八)(五)
2019-09-01 23:08:54 】 浏览:121
Tags:kmalloc 分配 物理 内存 高端 映射 --Linux 管理 十八
e gfp_t)___GFP_OTHER_NODE) /* Room for N __GFP_FOO bits */ #define __GFP_BITS_SHIFT 26 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))

给出的常数,其中一些很少使用,因此我不会讨论。其中最重要的一些常数语义如下所示

其中在开始的位置定义了对应的区修饰符, 定义在include/linux/gfp.h?v=4.7, line 46 ~ line 57

区修饰符标志 描述
__GFP_DMA 从ZONE_DMA中分配内存
__GFP_HIGHMEM 从ZONE_HIGHMEM或ZONE_NORMAL中分配内存
__GFP_DMA32 从ZONE_DMA32中分配内存
__GFP_MOVABLE 从__GFP_MOVABLE中分配内存

其次还定义了我们程序和函数中所需要的掩码MASK的信息, 由于其中__GFP_DMA, __GFP_DMA32, __GFP_HIGHMEM, __GFP_MOVABLE是在内存中分别有对应的内存域信息, 因此我们定义了内存域的掩码GFP_ZONEMASK, 参见include/linux/gfp.h?v=4.7, line 57

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

接着内核定义了行为修饰符

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

虽然名字相似,但__GFP_HIGH与__GFP_HIGHMEM毫无关系,请不要弄混这两者

行为修饰符 描述
__GFP_RECLAIMABLE
__GFP_MOVABLE
是页迁移机制所需的标志. 顾名思义,它们分别将分配的内存标记为可回收的或可移动的。这影响从空闲列表的哪个子表获取内存
__GFP_WRITE
__GFP_HARDWALL 只在NUMA系统上有意义. 它限制只在分配到当前进程的各个CPU所关联的结点分配内存。如果进程允许在所有CPU上运行(默认情况),该标志是无意义的。只有进程可以运行的CPU受限时,该标志才有效果
__GFP_THISNODE 也只在NUMA系统上有意义。如果设置该比特位,则内存分配失败的情况下不允许使用其他结点作为备用,需要保证在当前结点或者明确指定的结点上成功分配内存
__GFP_ACCOUNT
__GFP_ATOMIC
__GFP_HIGH 如果请求非常重要, 则设置__GFP_HIGH,即内核急切地需要内存时。在分配内存失败可能给内核带来严重后果时(比如威胁到系统稳定性或系统崩溃), 总是会使用该标志
__GFP_MEMALLOC
__GFP_NOMEMALLOC
__GFP_IO 说明在查找空闲内存期间内核可以进行I/O操作. 实际上, 这意味着如果内核在内存分配期间换出页, 那么仅当设置该标志时, 才能将选择的页写入硬盘
__GFP_FS 允许内核执行VFS操作. 在与VFS层有联系的内核子系统中必须禁用, 因为这可能引起循环递归调用.
__GFP_DIRECT_RECLAIM
__GFP_KSWAPD_RECLAIM
__GFP_RECLAIM
__GFP_REPEAT 在分配失败后自动重试,但在尝试若干次之后会停止
__GFP_NOFAIL 在分配失败后一直重试,直至成功
__GFP_NORETRY 在分配失败后不重试,因此可能分配失败
__GFP_COLD 如果需要分配不在CPU高速缓存中的“冷”页时,则设置__GFP_COLD
__GFP_NOWARN 在分配失败时禁止内核故障警告。在极少数场合该标志有用
__GFP_COMP 添加混合页元素, 在hugetlb的代码内部使用
__GFP_ZERO 在分配成功时,将返回填充字节0的页
__GFP_NOTRACK
__GFP_NOTRACK_FALSE_POSITIVE
__GFP_NOTRACK
__GFP_OTHER_NODE

那自然还有__GFP_BITS_SHIFT来表示我们所有的掩码位, 由于我们共计26个掩码位

/* Room for N __GFP_FOO bits */
#define __GFP_BITS_SHIFT 26
#define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))

可以同时指定这些分配标志, 例如

ptr = kmalloc(size, __GFP_IO | __GFP_FS);

说明页分配器(最终会调用alloc_page)在分配时可以执行I/O, 在必要时还可以执行文件系统操作. 这就让内核有很大的自由度, 以便它尽可能找到空闲的内存来满足分配请求. 大多数分配器都会执行这些修饰符, 但一般不是这样直接指定, 而是将这些行为描述符标志进行分组, 即类型标志

3.3.4 掩码分组

最后来看第三部分, 由于这些标志几乎总是组合使用,内核作了一些分组,包含了用于各种标准情形的适当的标志. 称之为类型标志, 定义在include/linux/gfp.h?v=4.7, lien 194 ~ line 258

类型标志指定所需的行为和区描述符以安城特殊类型的处理, 正因为这一点, 内核总是趋于使用正确的类型标志, 而不是一味地指定它可能用到的多种描述符. 这么做既简单又不容易出错误.

如果有可能的话, 在内存管理子系统之外, 总是把下列分组之一用于内存分配. 在内核源代码中, 双下划线通常用于内部数据和定义. 而这些预定义的分组名没有双下划线前缀, 点从侧面验证了上述说法.

#define GFP_ATOMIC      (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)
#define GFP_KERNEL      (__GFP_RECLAIM | __GFP_IO | __GFP_FS)
#define GFP_KERNEL_ACCOUNT (GFP_KERNEL | __GFP_ACCOUNT)
#define GFP_NOWAIT      (__GFP_KSWAPD_RECLAIM)
#define GFP_NOIO        (__GFP_RECLAIM)
#define GFP_NOFS        (__GFP_RECLAIM | __GFP_IO)
#define GFP_TEMPORARY   (__GFP_RECLAIM | __GFP_IO | __GFP_FS | \
                         __GFP_RECLAIMABLE)
#define GFP_USER        (__GFP_RECLAIM | __GFP_IO | __GFP_FS | __GFP_HARDWALL)
#define GFP_DMA         __GFP_DMA
#define GFP_DMA32       __GFP_DMA32
#define GFP_HIGHUSER    (GFP_USER
首页 上一页 2 3 4 5 6 下一页 尾页 5/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇System.map文件的作用 下一篇痞子衡嵌入式:开启NXP-MCUBootUt..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目