设为首页 加入收藏

TOP

深度解读 Linux 内核级通用内存池 —— kmalloc 体系(一)
2023-07-23 13:27:06 】 浏览:64
Tags:解读 Linux 通用内 kmalloc 体系

image

本文是笔者 slab 系列的最后一篇文章,为了方便大家快速检索,先将相关的文章列举出来:

在之前的这四篇文章中,笔者详细的为大家介绍了 slab 内存池的整体架构演化过程,随后基于这个演化过程,介绍了整个 slab alloactor 体系的创建,内存分配,内存释放以及销毁等相关复杂流程在内核中的实现。

我们知道 slab 内存池是专门为了应对内核中关于小内存分配需求而应运而生的,内核会为每一个核心数据结构创建一个专属的 slab 内存池,专门用于内核核心对象频繁分配和释放的场景。比如,内核中的 task_struct 结构,mm_struct 结构,struct page 结构,struct file 结构,socket 结构等等,在内核中都有一个属于自己的专属 slab 内存池。

而之前介绍的这些都属于专有的 slab 内存池,slab 在向伙伴系统申请若干物理内存页 page 之后,内核会按照需要被池化的专有数据结构在内存中的布局 size,从这些物理内存页中划分出多个大小相同的内存块出来,然后将这些划分出来的内存块统一交给其所属的 slab 内存池管理。每个内存块用来专门存储特定结构的内核对象,不能用作其他用途。

image

内核中除了上述这些专有内存的分配需求之外,其实更多的是通用小内存的分配需求,比如说,内核会申请一些 8 字节,16 字节,32 字节等特定尺寸的通用内存块,内核并不会限制这些通用内存块的用途,可以拿它们来存储任何信息。

内核为了应对这些通用小内存的频繁分配释放需求,于是本文的主题 —— kmalloc 内存池体系就应用而生了,在内核启动初始化的时候,通过 kmem_cache_create 接口函数预先创建多个特定尺寸的 slab cache 出来,用以应对不同尺寸的通用内存块的申请。

struct kmem_cache *
kmem_cache_create(const char *name, unsigned int size, unsigned int align,
        slab_flags_t flags, void (*ctor)(void *))

我们可以通过 kmem_cache_create 函数中的 size 参数来指定要创建的通用内存块尺寸,相关的创建流程细节,感兴趣的同学可以回看下这篇文章 《从内核源码看 slab 内存池的创建初始化流程》

kmalloc 内存池体系的底层基石是基于 slab alloactor 体系构建的,其本质其实就是各种不同尺寸的通用 slab cache。

image

我们可以通过 cat /proc/slabinfo 命令来查看系统中不同尺寸的通用 slab cache:

image

kmalloc-32 是专门为 32 字节的内存块定制的 slab cache,用于应对 32 字节小内存块的分配与释放。kmalloc-64 是专门为 64 字节的内存块定制的 slab cache,kmalloc-1k 是专门为 1K 大小的内存块定制的 slab cache 等等。那么 kmalloc 体系究竟包含了哪些尺寸的通用 slab cache 呢 ?

1. kmalloc 内存池中都有哪些尺寸的内存块

本文内核源码部分基于 5.4 版本讨论

内核将这些不同尺寸的 slab cache 分类信息定义在 kmalloc_info[] 数组中,数组中的元素类型为 kmalloc_info_struct 结构,里边定义了对应尺寸通用内存池的相关信息。

const struct kmalloc_info_struct kmalloc_info[];

/* A table of kmalloc cache names and sizes */
extern const struct kmalloc_info_struct {
    // slab cache 的名字
    const char *name;
    // slab cache 提供的内存块大小,单位为字节
    unsigned int size;
} kmalloc_info[];
  • size 用于指定该 slab cache 中所管理的通用内存块尺寸。
  • name 为该通用 slab cache 的名称,名称形式为 kmalloc-内存块尺寸(单位字节),这一点我们可以通过 cat /proc/slabinfo 命令查看。
const struct kmalloc_info_struct kmalloc_info[] __initconst = {
    {NULL,                      0},     {"kmalloc-96",             96},
    {"kmalloc-192",           192},     {"kmalloc-8",               8},
    {"kmalloc-16",             16},     {"kmalloc-32",             32},
    {"kmalloc-64",             64},     {"kmalloc-128",           128},
    {"kmalloc-256",           256},     {"kmalloc-512",           512},
    {"kmalloc-1k",           1024},     {"kmalloc-2k",           2048},
    {"kmalloc-4k",           4096},     {"kmalloc-8k",           8192},
    {"kmalloc-16k",         16384},     {"kmalloc-32k",         32768},
    {"kmalloc-64k",         65536},     {"kmalloc-128k",       131072},
    {"kmalloc-256k",       262144},     {"kmalloc-512k",       524288},
    {"kmalloc-1M",        1048576},     {"kmalloc-2M",        2097152},
    {"kmalloc-4M",        4194304},     {"kmalloc-8M",        8388608},
    {"kmalloc-16M",      16777216},     {"kmalloc-32M",      33554432},
    {"kmalloc-64M",      67108864}
};

从 kmalloc_info[] 数组中我们可以看出,kmalloc 内存池体系理论上最大可以支持 64M 尺寸大小的通用内存池。

kmalloc_info[] 数组中的 index 有一个特点,从 index = 3 开始一直到数组的最后一个 index,这其中的每一个 index 都表示其对应的 kmalloc_info[index] 指向的通用 slab cache 尺寸,也就是说 kmalloc 内存池体系中的每个通用 slab cache 中内存块的尺寸由其所在的 kmalloc_info[] 数组 index 决定,对应内存块大小为:2^index 字节,比如:

  • kmalloc_info[3] 对应的通用 slab cache 中所管理的内存块尺
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 1/8/8
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇ELK日志收集记录 下一篇cockpit--一款开源的适用于单主机..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目