开发笔记-linux内核编译过程中的memcg SLUB sysfs 支持异常处理

1.概要

2.内容

1.Enable memcg SLUB sysfs support by default

要默认启用 memcg SLUB sysfs 支持,您需要在 Linux 内核配置中启用相关选项。这通常涉及到配置和编译内核的过程。以下是您可以遵循的步骤:

  1. 获取内核源代码
    首先,确保您有 Linux 内核的源代码。您可以从 Linux 内核的官方网站 下载最新版本的内核源代码。

  2. 配置内核
    进入内核源代码目录,并使用以下命令之一来配置内核:

    • make menuconfig(图形界面,需要安装依赖)
    • make nconfig(新的图形界面,基于 ncurses)
    • make xconfig(图形界面,基于 Qt)
    • make oldconfig(基于旧配置进行更新)
    • 直接编辑 .config 文件
  3. 启用 memcg SLUB sysfs 支持
    在配置界面中,您需要找到并启用与 memcg(内存控制组)和 SLUB(Simple Linear Unbounded kmalloc/kfree 实现)相关的选项。具体路径可能因内核版本而异,但通常您可以在以下位置找到相关选项:

    • 前往 “General setup” 或 “Memory management” 部分。
    • 查找 “Enable the memory controller (memcg) SLUB sysfs interface” 或类似的选项。
    • 确保该选项被选中(通常是通过按 Y 键)。

    如果您直接编辑 .config 文件,可以添加或确保以下行存在:

    CONFIG_MEMCG_SLUB_SYSFS=y
  4. 编译内核
    保存配置后,您可以开始编译内核:

    make -j $(nproc)

    这里 -j $(nproc) 选项会利用所有可用的处理器核心来加快编译速度。

  5. 安装新内核
    编译完成后,您需要安装新内核。这通常涉及到复制内核镜像到 /boot 目录,并更新引导加载器(如 GRUB)。具体步骤取决于您的系统分布。

  6. 重启并验证
    重启系统以使用新内核,并验证 memcg SLUB sysfs 支持是否已启用。您可以通过检查 /sys/kernel/slub 目录下的相关文件来确认。

请注意,这些步骤可能会因您使用的 Linux 发行版和内核版本而略有不同。如果您使用的是特定的发行版(如 Ubuntu、Debian 等),可能还有特定的工具和命令来帮助您配置和编译内核。此外,始终建议在生产环境中测试新内核之前,先在测试环境中进行充分测试。

2.问题处理 

问题:

UPD     include/generated/utsrelease.h
warning: Cannot use CONFIG_STACK_VALIDATION=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel
error: Cannot resolve BTF IDs for CONFIG_DEBUG_INFO_BTF, please install libelf-dev, libelf-devel or elfutils-libelf-devel
make: *** [Makefile:1273:prepare-resolve_btfids] 错误 1

处理方法:

您在编译 Linux 内核或某些依赖于内核的项目时遇到了错误和警告。这些错误和警告提示您需要安装特定的库文件,以便正确地进行编译。这里是具体的分析和解决步骤:

  1. 错误和警告分析
    • 警告Cannot use CONFIG_STACK_VALIDATION=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel
      此警告表明您尝试启用栈验证功能(CONFIG_STACK_VALIDATION),但系统中缺少必要的库文件来支持这一功能。
    • 错误Cannot resolve BTF IDs for CONFIG_DEBUG_INFO_BTF, please install libelf-dev, libelf-devel or elfutils-libelf-devel
      此错误说明在尝试解析 BTF(BPF Type Format)ID 时失败,原因同样是缺少必要的库文件。
  2. 解决方案
    • 您需要安装 libelf 的开发库。根据您使用的 Linux 发行版,可以选择安装以下包之一:
      • 对于基于 Debian 的系统(如 Ubuntu),使用:
        sudo apt-get update
        sudo apt-get install libelf-dev
      • 对于基于 Red Hat 的系统(如 CentOS 或 Fedora),使用:
        sudo yum install libelf-devel
        或者如果您使用的是 dnf(如在较新的 Fedora 版本中):
        sudo dnf install libelf-devel
      • 对于其他系统,可能需要查找对应的包管理器并安装 elfutils-libelf-devel
  3. 安装后的步骤
    • 安装完必要的库文件后,重新配置您的内核或项目(如果需要的话,确保 CONFIG_STACK_VALIDATION 和 CONFIG_DEBUG_INFO_BTF 等选项按需求设置)。
    • 重新编译项目。
  4. 验证
    • 编译完成后,确保没有错误或警告提示。
    • 如果问题依旧存在,检查是否所有依赖都已正确安装,并确认您的编译环境配置无误。

通过以上步骤,您应该能够解决编译过程中遇到的问题。如果还有其他问题,可能需要检查更详细的编译日志或寻求更专业的帮助。

3.Simple Linear Unbounded kmalloc/kfree 

在 Linux 内核编程中,kmalloc 和 kfree 是用于内存分配和释放的两个基础函数。尽管它们的使用相对直接,但不当使用这些函数可能导致一系列问题,比如内存泄漏、内存碎片以及更严重的错误如使用未初始化或已释放的内存。这里讨论的是“Simple Linear Unbounded kmalloc/kfree”,即简单线性无界内存分配和释放,这种情况下的内存使用模式可能导致一些特定的风险。

kmalloc

kmalloc 函数用于在内核空间分配内存。其基本原型如下:

void* kmalloc(size_t size, gfp_t flags);
  • size 是要分配的内存块的大小,以字节为单位。
  • flags 指定内存分配的行为特性,如是否可以在分配时睡眠等。

kfree

kfree 函数用于释放由 kmalloc 分配的内存。其原型为:

void kfree(const void *objp);
  • objp 是指向要释放的内存块的指针。

Simple Linear Unbounded Allocation

简单线性无界分配指的是在代码中连续不断地分配内存而不检查总的分配量,也没有适当的释放机制。这种模式可能出现在循环或重复调用的函数中,每次迭代都分配一定大小的内存,但不在适当的时候释放。

示例
void problematic_function(int num_iterations) {  
    for (int i = 0; i < num_iterations; i++) {  
        char *buffer = kmalloc(1024, GFP_KERNEL);  // 分配 1024 字节  
        if (!buffer) {  
            printk(KERN_ERR "Failed to allocate memory\n");  
            continue;  
        }  
        // 使用 buffer 做一些操作  
        // 注意这里没有 kfree(buffer),导致内存泄漏  
    }  
}

风险

  1. 内存泄漏:如果分配的内存没有被适当释放,系统的可用内存将逐渐减少,最终可能导致内存耗尽。
  2. 性能问题:频繁的内存分配和(缺乏的)释放可以导致内存碎片,影响系统性能。
  3. 系统崩溃:在极端情况下,无节制的内存分配可能导致系统崩溃或不稳定。

解决方案

  1. 确保释放:每次分配内存后,确保在不再需要时释放它。
  2. 使用适当的数据结构:如果需要动态管理多个内存块,考虑使用如链表、树等数据结构来组织这些内存块,以便于管理和释放。
  3. 错误处理:在分配内存时检查返回值,确保分配成功。如果失败,适当处理错误情况。
  4. 限制分配大小:如果可能,限制单次分配的内存大小以及总的分配次数,以避免无节制的内存使用。

通过谨慎地管理内存分配和释放,可以避免许多与内存相关的问题,确保系统稳定性和性能。

4. memcg SLUB sysfs 支持

在 Linux 内核中,memcg(memory cgroup)用于实现内存资源的隔离与限制功能,SLUB 是 Linux 内核中用于小内存分配的一种高效内存分配器,而 sysfs 是一个基于内存的虚拟文件系统,负责以设备树的形式向用户空间提供设备和驱动信息。以下是对这三个概念的详细解释以及它们之间关系的探讨。

memcg(Memory Cgroup)

memcg 是 cgroup 的一种,专门用于内存资源的管理。它允许将系统的内存资源划分给不同的 cgroup,并为每个 cgroup 设置内存使用的限制。这样,即使某个应用或进程出现内存泄漏,也不会影响系统的整体稳定性和其他应用或进程的运行。

SLUB(Slab Allocator)

SLUB 是 Linux 内核中用于小内存分配的一种高效内存分配器。与 slab 分配器相比,SLUB 简化了数据结构,提高了内存分配的效率。在 SLUB 中,kmem_cache 是用于管理每种缓存的数据结构,它负责内存的分配和释放。

sysfs

sysfs 是一个基于内存的虚拟文件系统,由 Linux 内核提供,并挂载到 /sys 目录下。它允许用户空间程序以文件系统的方式访问内核数据结构,如设备和驱动信息。sysfs 与 kobject 框架紧密联系,kobject 是为设备驱动模型而存在的,因此 sysfs 主要为设备和驱动提供服务。

memcg、SLUB 与 sysfs 的关系

在 Linux 内核中,memcgSLUB 和 sysfs 是三个相对独立但又相互关联的组件。以下是它们之间关系的简要说明:

  • memcg 与 SLUB:当 memcg 功能被启用时(通常默认启用),它会影响 SLUB 分配器的行为。特别是,memcg 会在 SLUB 的内存管理结构中引入额外的成员,如 memcg_params,用于记录 memcg 在 slab 相关的一些参数。这样,memcg 就可以对每个 cgroup 的内存使用情况进行统计和限制。
  • memcg 与 sysfsmemcg 会通过 sysfs 文件系统暴露其配置和状态信息。用户空间程序可以通过读取 /sys/fs/cgroup/memory 目录下的文件来了解 memcg 的配置和当前状态,也可以通过写入这些文件来修改 memcg 的配置。
  • SLUB 与 sysfs:虽然 SLUB 本身并不直接通过 sysfs 暴露其内部状态,但内核中的一些 sysfs 接口可能会间接反映 SLUB 的性能和行为。此外,如果 CONFIG_SLUB_DEBUG 等调试选项被启用,sysfs 可能会提供额外的调试信息。

总结

在 Linux 内核中,memcgSLUB 和 sysfs 是三个重要的组件,它们各自承担着不同的功能,但又相互关联、相互影响。memcg 通过 sysfs 提供内存资源的隔离和限制功能,而 SLUB 作为内存分配器,其行为会受到 memcg 的影响。同时,sysfs 也为内核和用户空间之间的信息交换提供了重要的桥梁。

5.在 Linux 内核中,memcg、SLUB 和 sysfs 是三个重要的组件

在Linux内核中,memcg(内存控制组)SLUB(Simple Low-friction User-friendly Buffer)分配器sysfs(System File System)是三个重要的组件,它们在系统资源管理、内存分配和内核信息访问方面发挥着关键作用。以下是对这三个组件的详细解释:

1. memcg(内存控制组)

功能与作用

  • 内存隔离与限制: memcg是cgroup(控制组)子系统的一部分,专门用于限制、隔离和监控不同进程组的内存使用。通过memcg,系统管理员可以对不同任务或进程组设置内存使用上限,防止某个进程过度消耗系统内存资源,确保系统的稳定性和公平性。
  • 内存计费与回收: memcg使用mem_cgroup_charge等函数对内存页进行“计费”,确保内存使用能够正确归属到对应的内存控制组中。当内存使用超过预设的限制时,系统会触发内存回收机制,甚至启动oom_killer(内存溢出杀手)来终止占用过多内存的进程。
  • 应用场景: memcg在云原生环境中尤为重要,它为实现容器化应用的内存隔离和限制提供了基础。通过memcg,容器平台可以确保每个容器只能使用分配给它的内存资源,避免容器之间的资源竞争。

工作原理

  • 内存分配与计费: 当进程尝试分配内存时,内核会调用相关函数将内存消耗计入对应的memcg。这通常涉及到修改内存页的结构,以便在后续的内存回收和统计过程中能够正确识别该内存页所属的cgroup。
  • 内存回收与oom_killer: 当某个memcg的内存使用超过限制时,系统会尝试回收内存。如果回收失败,系统会启动oom_killer,根据一定的策略选择并终止占用过多内存的进程,以释放内存资源。

2. SLUB分配器

功能与作用

  • 内存分配与回收: SLUB是Linux内核中的一种内存分配器,用于管理小块内存的分配和回收。它提高了内存分配的效率,减少了内存碎片,并简化了内存管理逻辑。SLUB分配器广泛应用于内核中的各种场景,特别是需要频繁创建和销毁小对象的场景,如网络栈、文件系统等。
  • 对象缓存: SLUB分配器通过对象缓存机制,将频繁使用的内核对象缓存起来,以减少分配、初始化和释放对象的时间开销。这种机制提高了系统的响应速度和性能。

工作原理

  • slab缓存: SLUB分配器基于slab缓存机制,将内存划分为多个固定大小的slab,每个slab包含多个相同大小的对象。当需要分配内存时,SLUB分配器会从相应的slab中获取一个空闲对象;当对象不再使用时,会将其释放回slab缓存中。
  • 内存管理结构: SLUB分配器使用kmem_cachekmem_cache_cpukmem_cache_node等结构来管理内存分配。其中,kmem_cache表示一个对象缓存,kmem_cache_cpu用于管理每个CPU的缓存,kmem_cache_node用于管理NUMA节点的缓存。

3. sysfs

功能与作用

  • 内核信息访问: sysfs是一个虚拟文件系统,用于向用户空间提供对内核数据结构的访问。它提供了一个统一的接口,使用户空间程序可以通过文件操作的方式来访问和配置内核的各种信息。
  • 设备与驱动管理: sysfs为每个设备和驱动程序提供了一个目录,其中包含有关设备和驱动程序的信息,如设备名称、驱动程序名称、设备状态等。这有助于系统管理员和开发人员了解和管理系统中的设备和驱动程序。
  • 内核参数配置: 通过sysfs,用户空间程序可以动态地修改内核参数,从而改变内核的行为。这对于系统调优和故障排查非常有用。

工作原理

  • 文件系统挂载: sysfs通常被挂载在/sys目录下。当用户或程序访问/sys目录中的文件时,内核会提供相应的信息或执行相应的操作。
  • 信息展示与交互: sysfs通过文件接口提供设备或驱动的状态信息、配置选项等。用户可以通过读取这些文件来获取内核信息,或者通过写入文件来配置内核参数。

总结

  • memcg:用于实现内存资源的隔离与限制,确保系统的稳定性和公平性。
  • SLUB分配器:用于管理小块内存的分配和回收,提高内存分配效率和减少内存碎片。
  • sysfs:用于提供内核信息访问和配置接口,方便用户空间程序与内核进行交互。

这三个组件在Linux内核中相互协作,共同实现了高效的内存管理、资源隔离和内核信息访问功能。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值