kmalloc分配大小的限制

news/2024/11/8 9:01:54/

原文地址:http://linux.chinaunix.net/techdoc/net/2009/04/28/1109237.shtml

####################################################################################################################################

kmalloc是通过cache来实现的, 只不过每次kmalloc的大小不同, 因此是从不同的cache中分配:
/* include/linux/slab.h */
// 注意kmalloc是在头文件中定义的
static inline void *kmalloc(size_t size, gfp_t flags)
{
if (__builtin_constant_p(size)) {
// 以下是找一个对象大小刚好大于等于size的cache
  int i = 0;
#define CACHE(x) \
  if (size 
// 这是kmalloc_sizes.h文件内容, 实际就是定义CACHE中可用的对象大小
// 普通情况下最大是128K, 也就是kmalloc能分配的最大内存量
#if (PAGE_SIZE == 4096)
CACHE(32)
#endif
CACHE(64)
#if L1_CACHE_BYTES  512) || (MAX_NUMNODES > 256) || !defined(CONFIG_MMU)
CACHE(262144)
#endif
#ifndef CONFIG_MMU
CACHE(524288)
CACHE(1048576)
#ifdef CONFIG_LARGE_ALLOCS
CACHE(2097152)
CACHE(4194304)
CACHE(8388608)
CACHE(16777216)
CACHE(33554432)
#endif /* CONFIG_LARGE_ALLOCS */
#endif /* CONFIG_MMU
继续调用
void *__kmalloc(size_t size, gfp_t flags)
{
return __do_kmalloc(size, flags, NULL);
}

static __always_inline void *__do_kmalloc(size_t size, gfp_t flags,
       void *caller)
{
struct kmem_cache *cachep;
/* If you want to save a few bytes .text space: replace
  * __ with kmem_.
  * Then kmalloc uses the uninlined functions instead of the inline
  * functions.
  */
cachep = __find_general_cachep(size, flags);
if (unlikely(cachep == NULL))
  return NULL;
return __cache_alloc(cachep, flags, caller);
}

static inline struct kmem_cache *__find_general_cachep(size_t size, gfp_t gfpflags)
{
struct cache_sizes *csizep = malloc_sizes;
#if DEBUG
/* This happens if someone tries to call
  * kmem_cache_create(), or __kmalloc(), before
  * the generic caches are initialized.
  */
BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL);
#endif
while (size > csizep->cs_size)
  csizep++;
/*
  * Really subtle: The last entry with cs->cs_size==ULONG_MAX
  * has cs_{dma,}cachep==NULL. Thus no special case
  * for large kmalloc calls required.
  */
if (unlikely(gfpflags & GFP_DMA))
  return csizep->cs_dmacachep;
return csizep->cs_cachep;
}

__find_general_cachep确定可以分配的空间大小由malloc_sizes结构体数组指定,在阅读mm/slab.c中它的定义如下
struct cache_sizes malloc_sizes[] = {
#define CACHE(x) { .cs_size = (x) },
#include 
CACHE(ULONG_MAX)
#undef CACHE
};
在对一个结构体进行赋值的时候,第一次看到了这个用法,赶紧来仔细看看代码。
首先在slab_def.h中找到cache_sizes的定义如下:
struct cache_sizes { 
size_t cs_size; 
struct kmem_cache *cs_cachep; 
#ifdef CONFIG_ZONE_DMA 
struct kmem_cache *cs_dmacachep; 
#endif 
}; 
可以看出,无论cache_sizes的如何变,至少都要给cs_size分配一个值。函数一就是对malloc_sizes这个数组进行初始化。在初始化的时候却多了3行代码:
代码一:#define CACHE(x) { .cs_size = (x) }, 
作用:定义一个CACHE(x)的宏,作用在include里面。
代码二:#include  
作用,引用kmalloc_size.h文件。使malloc_sizes[]得到初始化的值。换个角度看,把函数初始化和依据附加条件分开,使得程序的逻辑更加清晰。在函数中,CACHE仅仅作为一个宏,与具体的实现无关。
代码三:#undef CACHE 
作用:撤销代码一中的定义。

综合来讲,实现的功能就是:
#include 把kmalloc_sizes.h文件里面的内容原封不动地复制到数组中, 定义了一个宏CACHE(x),用完之后取消。
数组展开之后便成:
struct cache_sizes malloc_sizes[] = {
       { .cs_size = (32) },
       { .cs_size = (64) },
       { .cs_size = (96) },
       ...
        { .cs_size = (ULONG_MAX) }
};
在linux/kmalloc_sizes.h中可以看到,所有的代码做的事,仅仅是针对不同的硬件环境作出不同的反应。除了默认的分配CHACH(x)运算外,针对内存页面、一级缓存大小,和是否支持内存管理模块,是否允许kmalloc分配大于1MB的内存等,分别作出了不同的动作。
在面向对象的编程中,最基本的三个概念为:继承、封装、抽象。继承可以理解为在在当前已经存在的基础上进行革新;封装也就是说将一些内部的东西不给你看,你只需要知道如何操作;抽象的意思就是程序有能力忽略正在处理中信息的某些方面,即对信息主要方面关注的能力。oop对于类的编程一般是这个流程:首先是对当前对象进行初始化,接着针对对象进行一系列的操作,最后对当前对象进行销毁
再回到文首的三个代码运行流程,代码一首先定义一个宏;代码二接收到这个值,并且进行一系列的操作,是内部的,在slab.c中没有描述;代码三,销毁代码一定义的宏。同时,在mm/slab.c和include/linux/slab_def.h中可以多次看到上述三个代码,只是在每个代码的实现中,CACHE(x)定义为不同的宏。

用于kmalloc可分配的内存大小范围在32~131027(128k)字节,并且由于它用slab分配器来分配内存的,所以,得到的内存大小可能比你申请的要大一些(它向上取2的N次幂整数)。而且如果开启了CONFIG_LARGE_ALLOCS选项,这个值可以更大,可以达到了32M。
 


http://www.ppmy.cn/news/241118.html

相关文章

采用链接分配方式进行外存分配时,可采用的两种形式及其特点。假定磁盘块大小为4K,对于128G的硬盘,其文件分配表FAT需占用多少存储空间?

采用链接分配方式进行外存分配时,可采用的两种形式及其特点。假定磁盘块大小为4K,对于128G的硬盘,其文件分配表FAT需占用多少存储空间? 隐式链接:除文件的最后一个盘快外,每个盘快中都存有指向下一个盘快的…

内存分配方式

一、内存分配方式 内存分配有三种方式: 1、从静态存储区分配。这种方式是在程序编译的时候已经分配好,并且这块内存在程序的整个运行期间都存在。如全局变量,static变量。 2、在栈上创建。在执行函数的时候,函数内局部变量的存储单…

kmalloc详解与分配大小的限制

kmalloc是通过cache来实现的, 只不过每次kmalloc的大小不同, 因此是从不同的cache中分配: /* include/linux/slab.h */ // 注意kmalloc是在头文件中定义的 static inline void *kmalloc(size_t size, gfp_t flags) {if (__builtin_constant_p(size)) { /*__builtin_constant_p…

java语言中 说明或声明数组时内存大小,说明或声明数组时不分配内存大小,创建数组时分配内存大小。...

试井过程中每一实测的压力、说明产量都不随时间变化的叫()。 或声学制具体规定着() 明数义务教育的主要特点() 组时组《中华人民共和国义务教育法》是哪一年颁布的?() 现代社会的迅速变化,不分以及高新科技的冲击,全世界都在进行着学校教育制…

linux安装分区大小分配

●文件系统 在windows下,我们常见到的文件系统有 FAT、 FAT32、 NTFS 在linux里可使用的文件系统有: Ext2:早期的格式,不支援日志 Ext3:是ext2改良版,增加了日志功能,是最基本且最常用的使用格式了。 ReiserFS:也有日志功能&#…

磁盘容量超过64T分配单元大小需要设置64K

转载于:https://www.cnblogs.com/Liangdalong/p/5894515.html

深度解析:2023年软件测试的10个新趋势和挑战

随着技术的飞速发展,软件测试的角色和责任也在经历重大转变。我们在2023年目前所面临的一些新趋势和挑战值得所有从业人员关注。以下是这些主要趋势和挑战的深度分析。 趋势一:人工智能和机器学习在测试中的应用 AI和ML正在越来越多地应用于软件测试&am…

exfat默认配置大小_U盘exFAT格式好不好?格式化分配单元大小多少合适?

2019年9月1日 通常,格式化分配单元越小,节省的空间越多。 分配单元越大,节省的时间越多,但浪费空间。 这看起来似乎分配单元小能节省空间,但事实并非如此。 文件分割的块越多,特别是当这些存储器单元分散时,它会浪费一些时间来读取数据。 分配单元大小是系统读取和写入磁…