kmalloc最大能申请多少内存?
1. 概述
本文主要分析kmalloc接口申请内存的大小情况,用于记录kmalloc分配内存的过程。
内核版本:Linux 4.9
2.分析记录
针对kmalloc最大能申请多少内存,网上众说纷纭,意见各不相同,因此最终决定自己针对源码分析,记录如下:
首先看kmalloc()函数实现,在include/linux/slab.h中,代码如下:
#ifdef CONFIG_SLAB
/** The largest kmalloc size supported by the SLAB allocators is* 32 megabyte (2^25) or the maximum allocatable page order if that is* less than 32 MB.** WARNING: Its not easy to increase this value since the allocators have* to do various tricks to work around compiler limitations in order to* ensure proper constant folding.*/
#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \(MAX_ORDER + PAGE_SHIFT - 1) : 25)
#define KMALLOC_SHIFT_MAX KMALLOC_SHIFT_HIGH
#ifndef KMALLOC_SHIFT_LOW
#define KMALLOC_SHIFT_LOW 5
#endif
#endif#ifdef CONFIG_SLUB
/** SLUB directly allocates requests fitting in to an order-1 page* (PAGE_SIZE*2). Larger requests are passed to the page allocator.*/
#define KMALLOC_SHIFT_HIGH (PAGE_SHIFT + 1)
#define KMALLOC_SHIFT_MAX (MAX_ORDER + PAGE_SHIFT - 1)
#ifndef KMALLOC_SHIFT_LOW
#define KMALLOC_SHIFT_LOW 3
#endif
#endif#ifdef CONFIG_SLOB
/** SLOB passes all requests larger than one page to the page allocator.* No kmalloc array is necessary since objects of different sizes can* be allocated from the same page.*/
#define KMALLOC_SHIFT_HIGH PAGE_SHIFT
#define KMALLOC_SHIFT_MAX (MAX_ORDER + PAGE_SHIFT - 1)
#ifndef KMALLOC_SHIFT_LOW
#define KMALLOC_SHIFT_LOW 3
#endif
#endif/* Maximum allocatable size */
#define KMALLOC_MAX_SIZE (1UL << KMALLOC_SHIFT_MAX)
/* Maximum size for which we actually use a slab cache */
#define KMALLOC_MAX_CACHE_SIZE (1UL << KMALLOC_SHIFT_HIGH)
/* Maximum order allocatable via the slab allocagtor */
#define KMALLOC_MAX_ORDER (KMALLOC_SHIFT_MAX - PAGE_SHIFT)static __always_inline void *kmalloc(size_t size, gfp_t flags)
{if (__builtin_constant_p(size)) {if (size > KMALLOC_MAX_CACHE_SIZE)return kmalloc_large(size, flags);
#ifndef CONFIG_SLOBif (!(flags & GFP_DMA)) {int index = kmalloc_index(size);if (!index)return ZERO_SIZE_PTR;return kmem_cache_alloc_trace(kmalloc_caches[index],flags, size);}
#endif}return __kmalloc(size, flags);
}
其中__builtin_constant_p()是编译器内函数,用于判断传入的参数是否为常量,因此动态分配内存一般不会进入该if分支,重点分析__kmalloc()实现即可。
__kmalloc()实现分三种情况,一种是slab,一种是slub,最后一种是slob,其实现分别如下:
2.1 slab的kmalloc()
static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,unsigned long caller)
{struct kmem_cache *cachep;void *ret;if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))return NULL;cachep = kmalloc_slab(size, flags);if (unlikely(ZERO_OR_NULL_PTR(cachep)))return cachep;ret = slab_alloc(cachep, flags, caller);kasan_kmalloc(cachep, ret, size, flags);trace_kmalloc(caller, ret,size, cachep->size, flags);return ret;
}void *__kmalloc(size_t size, gfp_t flags)
{return __do_kmalloc(size, flags, _RET_IP_);
}
EXPORT_SYMBOL(__kmalloc);
当Linux系统配置的内存管理器为slab时,如果分配的内存大于KMALLOC_MAX_CACHE_SIZE,就直接返回NULL,因此支持slab分配器的系统,kmalloc()分配的内存不能超过KMALLOC_MAX_CACHE_SIZE,该宏的计算见include/linux/slab.h。
当MAX_ORDER=11,PAGE_SHIFT=12(4kB)时,KMALLOC_MAX_CACHE_SIZE算出来是4MB,说明支持slab的系统,通过kmalloc()最大申请的内存不能超过4M。
但该值是跟随CONFIG_FORCE_MAX_ZONEORDER配置项和PAGE_SHIFT这两个宏决定。因此具体还需要看系统中这两个宏的值。
2.2 slub的kmalloc()
//mm/slub.c
void *__kmalloc(size_t size, gfp_t flags)
{struct kmem_cache *s;void *ret;if (unlikely(size > KMALLOC_MAX_CACHE_SIZE))return kmalloc_large(size, flags);s = kmalloc_slab(size, flags);if (unlikely(ZERO_OR_NULL_PTR(s)))return s;ret = slab_alloc(s, flags, _RET_IP_);trace_kmalloc(_RET_IP_, ret, size, s->size, flags);kasan_kmalloc(s, ret, size, flags);return ret;
}
EXPORT_SYMBOL(__kmalloc);
//mm/slab_common.c
void *kmalloc_order(size_t size, gfp_t flags, unsigned int order)
{void *ret;struct page *page;flags |= __GFP_COMP;page = alloc_pages(flags, order);ret = page ? page_address(page) : NULL;kmemleak_alloc(ret, size, 1, flags);kasan_kmalloc_large(ret, size, flags);return ret;
}
EXPORT_SYMBOL(kmalloc_order);
当Linux系统配置的内存管理器为slub时,如果分配的内存大于KMALLOC_MAX_CACHE_SIZE,就通过kmalloc_large()接口分配内存,最终会调用到kmalloc_order()函数,该函数直接从buddy子系统分配pages。因此只要系统上内存足够,就可以分配出足够大的内存,只是该内存不是属于slub管理器管理的对象而已。
系统支持slub内存管理器,KMALLOC_MAX_CACHE_SIZE宏的值只和PAGE_SHIFT有关,当PAGE_SHIFT=12时,KMALLOC_MAX_CACHE_SIZE算出来是8kB
2.3 slob的kmalloc()
//mm/slob.cstatic __always_inline void *
__do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller)
{unsigned int *m;int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);void *ret;gfp &= gfp_allowed_mask;lockdep_trace_alloc(gfp);if (size < PAGE_SIZE - align) {if (!size)return ZERO_SIZE_PTR;m = slob_alloc(size + align, gfp, align, node);if (!m)return NULL;*m = size;ret = (void *)m + align;trace_kmalloc_node(caller, ret,size, size + align, gfp, node);} else {unsigned int order = get_order(size);if (likely(order))gfp |= __GFP_COMP;ret = slob_new_pages(gfp, order, node);trace_kmalloc_node(caller, ret,size, PAGE_SIZE << order, gfp, node);}kmemleak_alloc(ret, size, 1, gfp);return ret;
}void *__kmalloc(size_t size, gfp_t gfp)
{return __do_kmalloc_node(size, gfp, NUMA_NO_NODE, _RET_IP_);
}
EXPORT_SYMBOL(__kmalloc);
当Linux系统配置的内存管理器为slob时,如果分配的内存大于PAGE_SIZE,就会从buddy子系统分配pages。因此只要系统上内存足够,就可以分配出足够大的内存。
3.结论
综上所述,kmalloc()能分配多大内存,是依赖系统的配置决定。
kmalloc最大能申请多少内存?相关推荐
- 通过伙伴系统申请内核内存的函数有哪些?
本文转自:http://blog.chinaunix.net/space.php?uid=22566367&do=blog&id=2747207 在物理页面管理上实现了基于区的伙伴系统 ...
- linux申请大块内存,linux 内存看一篇就够了(多图)
image 正文 0 内存模块 image 1 linux内存总体布局:内存分成用户态和内核态 4G进程地址空间解析 image image 内核地址空间 image image 进程地址空间 ima ...
- linux 用户进程结束后 malloc申请的内存会自动释放吗,进程退出后malloc的内存是否会被释放?
当一个进程退出后,不管是正常退出或者是异常退出,操作系统都会释放这个进程的资源.包括这个进程分配的内存,打开的文件等等. 内存泄露的前提是进程一直在运行:进程一旦退出,所占的整个虚拟内存都被销毁,所有 ...
- 【三分钟学习FFMPEG一个知识点】FFMPEG关于avio_alloc_context申请使用内存释放问题
问题: 使用ffmpeg发现av_malloc申请的内存最后不能用av_free函数释放,会崩溃. 代码示例: unsigned char * iobuffer = NULL; iobuffer = ...
- Yarn申请的内存的精确计算(转载+应用到自己的情况中)
这篇博客主要是利用[1]中的流程来尝试估算自己在运行spark on yarn模式时申请的内存数值. 一个spark任务会产生几个Container? count = ExecutorNum + 1 ...
- 关于用函数指针参数申请动态内存的问题
今天在写一个Binary Search Tree的程序时,发现其插入有问题,下面是插入程序,每次插入完成后,节点还是NULL. template<typename Object> void ...
- c语言链表错误,C语言创建链表错误之通过指针参数申请动态内存实例分析
本文实例讲述了C语言创建链表中经典错误的通过指针参数申请动态内存,分享给大家供大家参考之用.具体实例如下: #include #include // 用malloc要包含这个头文件 typedef s ...
- C语言为四维数组申请动态内存空间的方法(二)
尝试了用堆栈的方式为四维数组申请动态内存空间,并将申请内存的操作封装成了子函数,方便在主程序中使用.希望对大家有用.代码如下: #include <stdio.h> #include &l ...
- C语言为四维数组申请动态内存空间的方法(一)
尝试了用结构体为四维数组申请动态内存空间,希望对大家有用.代码如下: #include <stdio.h> #include <stdlib.h>typedef struct ...
最新文章
- 2022-2028年中国润滑油基础油行业市场研究及前瞻分析报告
- Microbiome:南土所褚海燕组揭示长期施肥抑制根际微生物固氮的作用机制
- Tomcat单向Https验证搭建,亲自实现与主流浏览器、Android/iOS移动客户端安全通信
- 复制表数据和结构的方法
- Mysql数据库设计及常见问题
- web服务器获取项目路径问题,读取web项目properties文件路径 解决tomcat服务器找不到properties路径问题...
- Missed in my life《2013》
- java清屏_【图片】请问java编写中如何做到清屏啊。。。_java吧_百度贴吧
- 2. 性能测试中常见术语集合
- 金融市场中的NLP——情感分析
- 2021年软考网络工程师备考资料
- 《HTTP权威指南》– 6.代理
- HoG特征以及SVM的配合
- 群辉 DSM 7.0 Docker 启动 AdguardHome 屏蔽广告
- c语言此项目已过期是什么意思,Visual Studio 2017 许可证已过期解决方案
- C语言程序课程设计—读心术
- 5分绩点转4分_4分绩点与百分制转换方法
- rtsp有没有好使_求几个可用的稍微清晰点的RTSP播放源,最好是上海的!
- 初学爬虫-笔趣阁爬虫
- 新功能上线 | “性能怪兽”Amazon Graviton2 正式登陆亚马逊云科技中国区域!