博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[内核内存] slab分配器3---kmem_cache_init函数源码详解
阅读量:4281 次
发布时间:2019-05-27

本文共 6407 字,大约阅读时间需要 21 分钟。

kmem_cache_init函数源码详解

//mm/slab.c/* * Initialisation.  Called after the page allocator have been initialised and * before smp_init(). *slab系统初始化时伙伴系统已经初始化,但在多处理器系统上,启动CPU此时正在运行, 而其他CPU尚未初始化. */void __init kmem_cache_init(void){
int i; BUILD_BUG_ON(sizeof(((struct page *)NULL)->lru) < sizeof(struct rcu_head)); /* *(1)kmem_cache_boot为编译时创建的静态数据,使用时不用内存分配,用作slab系统的第一个slab cache,为其它所有 * 的struct kmem_cache结构分配obj. *(2)kmem_cache是一个全局的静态变量struct kmem_cache *kmem_cache *(3)将编译时创建的静态数据变量kmem_cache_boot的地址赋值给全局静态变量kmem_cache */ kmem_cache = &kmem_cache_boot; if (!IS_ENABLED(CONFIG_NUMA) || num_possible_nodes() == 1) use_alien_caches = 0; /* *初始化静态定义的kmem_cache_node数组成员 * a.NUM_INIT_LISTS = 2 * MAX_NUMNODES,可以看出给每个node静态定义了两个kmem_cache_node变量,why? * b.实际上init_kmem_cache_node是为slab系统初始化过程中前两个struct kmem_cache实例的node成员提供存储空间, * 因为这两个实例初始化时,slab系统还未启动完全,因此仍然只能用静态变量的形式给他们的node成员提供存储空间 * (1)第一个stcruct kmem_cache实例,就是函数开始时进行赋值操作的全局静态变量kmem_cache,该实例给其他 * stcrut kmem_cache结构的创建提供内存空间(字节计数的小块内存) * (2)第二个struct kmem_cache实例是创建struct kmem_cache_node结构的slab cache描述符,该实例就是给stuct * kmem_cache_node结构数据提供小块内存。 *ps:全局静态变量kmem_cache使用时虽然不用分配内存,但是它的node成员只是一个地址指针,它指向的区域还没有分配 *内存空间,此时slab系统仍然未初始化完全,所以仍然只能用静态变量预定义的方式,来为kmem_cache的node成员指向的 *区域分配空间。 */ for (i = 0; i < NUM_INIT_LISTS; i++) kmem_cache_node_init(&init_kmem_cache_node[i]); /* * Fragmentation resistance on low memory - only use bigger * page orders on machines with more than 32MB of memory if * not overridden on the command line. */ if (!slab_max_order_set && totalram_pages > (32 << 20) >> PAGE_SHIFT) slab_max_order = SLAB_MAX_ORDER_HI; /* Bootstrap is tricky, because several objects are allocated * from caches that do not exist yet: * 1) initialize the kmem_cache cache: it contains the struct * kmem_cache structures of all caches, except kmem_cache itself: * kmem_cache is statically allocated. * Initially an __init data area is used for the head array and the * kmem_cache_node structures, it's replaced with a kmalloc allocated * array at the end of the bootstrap. * 2) Create the first kmalloc cache. * The struct kmem_cache for the new cache is allocated normally. * An __init data area is used for the head array. * 3) Create the remaining kmalloc caches, with minimally sized * head arrays. * 4) Replace the __init data head arrays for kmem_cache and the first * kmalloc cache with kmalloc allocated arrays. * 5) Replace the __init data for kmem_cache_node for kmem_cache and * the other cache's with kmalloc allocated memory. * 6) Resize the head arrays of the kmalloc caches to their final sizes. */ /* 1) create the kmem_cache */ /* * struct kmem_cache size depends on nr_node_ids & nr_cpu_ids *初始化 boot kmem_cache:主要是给第一个slab cache的各个成员赋值: * (a)kmem_cache->node:指向init_kmem_cache_node的前一半空间. * (b)kmem_cache->cpu_cache:通过__alloc_percpu函数来给该Per_CPU变量分配存储空间(分配array_cache实例). * 这时启动cpu正在运行,其他cpu还未初始化。这个时候只是按照固定大小给每个cpu分配一个本地高速缓存,且不会 * 给kmem_cache->node数组成员的每个节点的分配共享cpu高速缓存,即是kmem_cache->shared=0.后面待所有cpu都 * 初始化完全后,会调用kmem_cache_init_late函数完善cache_chain链表上所有struct kmem_cache实例的cpu本 * 地高速缓存和其每个节点共享cpu缓存的实现。 * (c)函数的第3个参数表示的是kmem_cache中每个slab obj的大小,SLAB_HWCACHE_ALIGN要求按硬件的cache line对 * 齐(一个或多个slab obj按硬件的cache line对齐) */ create_boot_cache(kmem_cache, "kmem_cache", offsetof(struct kmem_cache, node) + nr_node_ids * sizeof(struct kmem_cache_node *), SLAB_HWCACHE_ALIGN); //boot kmem_cache初始化完后,将其加入到slab_caches全局链表中. list_add(&kmem_cache->list, &slab_caches); //slab_state全局的enum类型,表示slab系统初始化当前处于哪个状态状态 slab_state = PARTIAL; /*2)-4)步骤执行 * Initialize the caches that provide memory for the kmem_cache_node * structures first. Without this, further allocations will bug. *创建第二个slab cache描述符,并将该描述符存储在kmalloc_caches全局数组中: * (a)kmalloc_caches是一个全局变量(struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1]),数组中 * 存储的是通用slab cache描述符(struct kemem_cache实例).kmalloc函数分配内存的时候,会根据所需要分配的 * 空间的大小,计算出一个索引值,然后利用索引值在kmalloc_caches数组中找到对应的kmem_cache实例,用该实例来 * 分配slab obj. * (b)kmalloc_size:(1)中讲到会根据kmalloc函数参数中分配内存的大小(size)获取到其对应slab cache描述符在 * kmalloc_caches数组中的索引index,这我们可以利用文档后面的kmalloc_index函数来获取: * index = kmalloc_index(size) * 而kmalloc_size函数是利用index来获得size: * size = kmalloc_size(index) * (c)#define INDEX_NODE kmalloc_index(sizeof(struct kmem_cache_node)) * 由上面的信息可以看出,此处就是创建一个struct kmem_cache_node结构体对应的slab cache描述符,然后将该slab * cache描述符存储在通用slab cache描述符数组kmalloc_caches的INDEX_NODE索引处(INDEX_NODE根据struct * kmem_cache_node结构体的大小获取)。 * ps:1.该函数结束后全局数组kmalloc_caches只有INDEX_NODE索引出由数据,其他位置仍然未赋值。 * 2.kmalloc_caches[INDEX_NODE]对应的slab cache描述符除了再全局数组中,还会添加到slab_caches链表中. * 3.第二个slab cache描述(kmalloc_caches[INDEX_NODE]),它的node成员指向的区域是init_kmem_cache_node * 数组的后半部分,也是静态定义的数据区 */ kmalloc_caches[INDEX_NODE] = create_kmalloc_cache("kmalloc-node", kmalloc_size(INDEX_NODE), ARCH_KMALLOC_FLAGS); //kmalloc size for node struct available,该状态下kmalloc函数能为struct kmem_cache_node结构体分配内存了 slab_state = PARTIAL_NODE; setup_kmalloc_cache_index_table(); slab_early_init = 0; /* 5) Replace the bootstrap kmem_cache_node */ /* *此时slab_state = PARTIAL_NODE,也就是slab系统中的kmalloc能够动态地为struct kmem_cache_node结构分 *配内存了.下面代码块的工作是将slab系统初始化时最先创建的两个slab cache描述符实例中的node指向的静态数据区替 *换成kmalloc动态分配内存区. * (a)对于kmem_cache: 用kmalloc函数动态地为每个节点分配一个struct kmem_cache_node,然后将kmem_cache->node * 指向的静态数据区中的内容按节点先后顺序拷贝到新分配struct kmem_cache_node中,最后将kmem_cache->node指 * 向新分配struct kmem_cache_node的地址处 * (b)对于kmalloc_caches[INDEX_NODE]:处理方式同上. *替换的原因貌似是静态定义的__initdata在某个时刻会被自动释放。 */ {
int nid; for_each_online_node(nid) {
init_list(kmem_cache, &init_kmem_cache_node[CACHE_CACHE + nid], nid); init_list(kmalloc_caches[INDEX_NODE], &init_kmem_cache_node[SIZE_NODE + nid], nid); } } /* *(1)丰富kmalloc_caches全局数组中通用slab cache描述符的类型,[0,PAGE_SHIFT)区间内每个元素都为其分配一个对应 * 的slab cache描述符,并指向它.这样更多不同大小的内存块分配需求都能很快通过kmalloc函数来满足.比如: * kmalloc_caches[1]对应的slab cache描述符能满足0-8字节内的所有内存分配需求,kmalloc_caches[2]能满足8-16 * 字节内的所有内存分配依次类推..... *(2)这样能提高slab系统kmalloc函数内存分配速度:因为各种大小区间的slab cache描述已经换成在全局数组中, * kmalloc分配内存时不需临时分配slab cache描述符。另外这些slab cache描述符中还缓存了很多未释放到伙伴系统 * 中的同等大小的内存块对象(slab obj),甚至有些slab obj还在本地cpu高速缓存中。 */ */ create_kmalloc_caches(ARCH_KMALLOC_FLAGS);}

转载地址:http://fpbgi.baihongyu.com/

你可能感兴趣的文章
工作队列 (一) workqueue demo
查看>>
工作队列 (二) 杂谈
查看>>
工作队列 (三) 数据结构与api
查看>>
串口 (一) 协议
查看>>
串口 (二) 串口硬件及操作-51单片机
查看>>
串口 (二) 串口硬件及操作-stm32
查看>>
串口 (三) linux串口
查看>>
串口 (四) linux串口之驱动代码
查看>>
串口 (五) linux串口之应用
查看>>
I2C (一) 协议
查看>>
I2C (二) 硬件操作
查看>>
I2C (三) linux I2C
查看>>
I2C (四) linux I2C 驱动代码
查看>>
I2C (五) linux I2C 与 sysfs
查看>>
SPI (一) 协议
查看>>
SPI (二) 硬件操作
查看>>
SPI (三) linux SPI
查看>>
网卡 (一) 1 LAN简介
查看>>
网卡 (五) LWIP ip模块
查看>>
网卡 (六) LWIP udp模块
查看>>