当前位置: 首页 > news >正文

linux-内存相关

在 Linux 内核开发中,内存申请接口包括:
根据分配粒度(字节 vs 页)、内存连续性(物理连续 vs 虚拟连续)以及分配器层级,可以将这些接口分为以下四大类:


1. 基于字节的分配接口 (Slab 分配器层级)

这是驱动开发中最常用的接口,用于分配小块内存(结构体、缓冲区等)。

kmalloc()

特点:物理地址和虚拟地址均连续。

底层:基于 Slab/Slub 分配器。

场景:分配小内存(通常 < 128KB),支持 DMA,速度快。

标志:必须指定 GFP_KERNEL(进程上下文,可休眠)或 GFP_ATOMIC(中断上下文,不可休眠)。


kzalloc()

特点:等同于 kmalloc 后自动调用 memset(0) 清零。


vmalloc()

特点:虚拟地址连续,物理地址不连续。

场景:分配大内存(如内核模块、大型缓冲区),不支持 DMA。


kmem_cache_alloc()

特点:用于分配固定大小的专用对象池。

场景:频繁创建/销毁的内核对象(如 task_struct、inode),能显著减少内存碎片并提高缓存命中率。

2. 基于页的分配接口 (伙伴系统层级)

当你需要以“页”(通常是 4KB)为单位的大块内存时使用。
alloc_pages(gfp_mask, order)
特点:分配 $2^{order}$ 个连续物理页。

返回:返回指向第一个 struct page 结构体的指针。
__get_free_pages(gfp_mask, order)
特点:与 alloc_pages 类似。

返回:返回第一个页的内核逻辑地址(可以直接使用)。
get_zeroed_page(gfp_mask)
特点:分配一个页并清零。

3. 特殊用途的内存接口
dma_alloc_coherent()

场景:DMA 一致性内存分配。
特点:保证物理地址连续,且关闭了 CPU 缓存(或处理了缓存同步),确保硬件外设与 CPU 看到的数据一致。


ioremap()场景:I/O 内存映射。
特点:不是分配内存,而是将物理硬件寄存器地址(如网卡寄存器)映射到内核虚拟空间,以便 CPU 访问。


devm_* 系列 (Managed Allocations)示例:devm_kmalloc()
特点:设备资源管理。内存会绑定到 struct device。
当驱动程序卸载(Unbind/Remove)时,内核会自动释放这些内存,防止内存泄漏。

vmalloc的核心特性是:

在虚拟地址空间中是连续的,但在物理内存中通常是不连续的。

vmalloc 的本质是修改页表(Page Tables)。

工作流程:
查找空闲区域: 在 VMALLOC_START 到 VMALLOC_END 之间的虚拟地址空间中寻找一块足够大的连续区域。
逐页分配: 调用 alloc_page 多次,申请一堆物理上散落在各处的 4 KB 页面。
映射页表: 修改内核页表,将这些零散的物理页面映射到第一步找出的连续虚拟空间上。

为什么不直接全用 kmalloc?
在 Linux 早期(以及嵌入式设备中),物理内存非常有限。kmalloc 返回的物理连续内存极其宝贵,因为它是 DMA(直接内存访问) 操作的唯一选择。大多数硬件外设(如老式网卡、磁盘控制器)不支持 IOMMU,只能识别连续的物理地址。

vmalloc 的代价
性能损耗: vmalloc 必须频繁修改页表,这会导致 TLB(转换检测缓冲区) 刷新,增加 CPU 开销。
访问延迟: 相比 kmalloc 简单的一步偏移计算,vmalloc 必须经过多级页表查询。

准则: 优先使用 kmalloc。只有当你分配的内存大到 kmalloc 无法满足,或者你明确不需要物理连续性(如纯软件逻辑缓冲区)时,才考虑 vmalloc。

kmalloc:直接映射
kmalloc 分配的是 内核逻辑地址。在大多数体系结构(如 x86)中,这些地址与物理地址仅存在一个固定的偏移量。

机制: 它建立在 Slab/Slub 分配器 之上。

优势: 由于是线性映射,不需要修改 CPU 的页表,也不会引起 TLB(转换检测缓冲区)的频繁刷新。

vmalloc:页表映射
vmalloc 分配的是 内核虚拟地址。

机制: 它在内核虚拟地址空间的特定区域(VMALLOC_START 到 VMALLOC_END)寻找一段空闲的连续虚拟地址。然后从伙伴系统(Buddy System)中申请零散的物理页,最后通过修改内核页表将这些零散的物理页映射到这段连续的虚拟地址上。

劣势: 增加了页表查询的层级,访问速度比 kmalloc 慢。

思考:内存泄露怎么看?
在用户态,我们有 Valgrind。但在内核态,如果 kmalloc 了没 kfree,内存就慢慢枯竭了。

内核有一种叫 Kmemleak 的机制。它会定期扫描内存,如果发现一块内存没有任何指针指向它,它就会在快照中标记为“疑似泄露”。


查看当前内存分配:
如果你想在自己的系统上截取这张“快照”,除了 free -m 这种表层数据,你需要深入内核接口:

全局概览:cat /proc/meminfo
关注 Slab、VmallocUsed 和 MemFree。

详细布局:cat /proc/vmallocinfo
可以清晰地看到内核里哪段代码(函数名)调用了 vmalloc 申请了多少内存。

http://www.jsqmd.com/news/459368/

相关文章:

  • 第174章 第四卷中局 - 淬火成钢
  • 等保测评命令——华三(H3C)网络设备
  • Java 中 Set 集合
  • Nginx安全配置:隐藏版本号
  • Qt 数据库模块详解(从驱动编译到性能优化)
  • 2026年靠谱的防爆电伴热带品牌推荐:自限温电伴热带/工程用电伴热带/阻燃防爆电伴热带行业内口碑厂家推荐 - 行业平台推荐
  • 溯源过程
  • 阿里云购买服务器安装openclaw踩坑记录
  • 写了个页面分享此时此刻我在听的歌
  • 优选算法——分治(1):三路快排
  • 【更新至2024年】2013-2024年各省数字经济指数数据(含原始数据+计算代码+结果)
  • 1分钟,带你认识门窗五金系统!
  • Ubuntu 20.04 LTS 防止暴力破解
  • Unreal Engine 4核心概念解析:Pawn——游戏世界中的可操控化身
  • Methyltetrazine–PEG4–Mal 1802908-02-6 活细胞双靶点标记探针
  • 基于Simulink的鲁棒H∞整流器控制器设计
  • 【通俗易懂告诉你什么是人工智能/CNN/RNN/DL......】
  • 智能AI裂缝识别 裂缝图像分割识别 建筑物裂缝识别 建筑结构裂缝自动检测模型训练 道路桥梁病害识别算法10529期
  • Unreal Engine 4核心概念解析:Character——专为人形角色设计的终极“游戏化身”
  • 毕业设计:基于SpringBoot Ai和Vue的旅游攻略小程序(源码)
  • OpenClaw霸榜,Agent正悄无声息地干掉传统“App”!
  • Mac病毒清除过程, SimulatorTrampoline,提醒事项APP伪装 XcodeGhost,XCSSET类型
  • 刷题笔记:力扣第18题-四数之和
  • 华为 MetaERP 的内部交易协同,是基于元数据驱动的多组织模型 + 事件驱动的服务总线 + 分布式事务 + 智能对账引擎,实现内部交易从发起、协同、确认到对账、抵消的全链路自动化、数据同源、零差异
  • STM32CubeMX配置串口采集超声波传感器数据(四)
  • Android BLE 稳定连接管理器(Kotlin版)完整代码骨架(下篇)
  • 动态规划之背包问题详解(从入门到实战)
  • Kubernetes中的网络策略(Network Policies)
  • 华为 MetaERP 已成为核电行业国产替代的核心方案,以全栈自主可控为基础,通过联合共建模式深度适配核电高安全、强管控、长周期的行业特性,已在中核、中广核等龙头企业落地标杆项目
  • SAP(以 S/4HANA 为代表)通过多组织建模、多分类账(多账套)、多币种引擎、多会计准则并行四大核心机制,在统一数据模型(ACDOCA)上实现集团化、全球化、多准则的财务核算架构