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

41、【OS】【Nuttx】【OSTest】内存监控:堆空间申请

背景

接之前 blog
39、【OS】【Nuttx】【OSTest】内存监控:用户堆成员)
40、【OS】【Nuttx】【OSTest】内存监控:用户堆内存函数)
分析了用户堆的相关成员,以及用户堆的相关内存函数,接下来继续看用户内存的初始化

用户堆空间申请

用户堆内存初始化之前,会先申请堆空间,这里 heap_start 是指针,up_allocate_heap 传入指针的地址进入,可获取到指向申请到的堆空间地址
在这里插入图片描述

SIM

在 sim 环境上,可看到准备申请的堆空间大小为 64 MB
在这里插入图片描述
sim 环境上分配空间的函数如下,这里有两个关键点:mmap 函数,host_uninterruptible
在这里插入图片描述

mmap

这里思考个问题:用户堆内存分配为什么不用 malloc,而是用 mmap?先来看看二者的区别:

  • malloc:
    1、标准库函数,主要用于动态分配小块或中等大小内存,通过系统调用(如 sbrkmmap)来扩展堆空间,并管理这些内存块以供程序使用;
    2、管理多个小块内存,通常从堆空间中分配内存,并且可以处理频繁的分配和释放操作;
    3、控制选项较少,主要是分配和释放内存,无法直接设置内存区域的保护属性(如读、写、执行权限)
    4、分配的内存是堆管理器分配的,需要维护复杂的内存分配,释放记录,可能会导致堆碎片问题,且频繁的分配和释放操作会导致较高的资源开销,适用于大多数需要动态分配内存的场景,尤其是分配较小的内存块
  • mmap:
    1、系统调用,在虚拟地址空间中创建新的内存映射,主要用于文件映射、共享内存和匿名内存映射等高级内存管理任务(这里用的就是匿名内存映射,分配纯粹的虚拟内存),可以将文件内容映射到内存中,或创建不与任何文件关联的大块内存区域
    2、适合分配较大的连续内存块,且分配的内存块通常是页面对齐的(通常是4KB),适合需要长期持有较少变更的内存区域
    3、提供控制选项指定内存区域的保护属性(如 PROT_READ、PROT_WRITE、PROT_EXEC),可以选择是否与其他任务共享内存(如 MAP_SHARED 或 MAP_PRIVATE),或是进行匿名操作(如 MAP_AON)
    4、直接在虚拟地址空间中创建一个新的内存映射区域,不依赖于堆管理器,
    申请大块连续内存效率高,开销低,适合高级内存管理任务,如文件映射,共享内存

这里准备申请的堆空间是 64M,属于大块连续内存,当然 mmap 更合适

host_uninterruptible

该宏作用为屏蔽中断,这里其实有疑问,mmap 作为系统调用,操作系统内核会处理相关的同步和保护机制,以确保其正确性和安全性,在这里添加中断屏蔽是否属于画蛇添足?
在这里插入图片描述
来看下提交记录,两年前,有位 L 兄弟增加了中断屏蔽(后续又有老哥将其封装成了宏格式),之前一直是没有中断屏蔽的,直接用 mmap,不过其提交记录只有寥寥两句话 sim/mem: don’t let siwtch out when operated the host mem,也没有贴出更多详细信息,所以这里是否有必要添加中断屏蔽,值得商榷
在这里插入图片描述
在这里插入图片描述
总而言之,sim 环境不是研究重点,更多应该是研究嵌入式环境下的内存分配,下面以 arm 为例,看下内存申请如何进行

arm common

来看下在 arm 中,其弱函数的定义,有几个关键点:link time 和 SRAM,这意味着可分配的堆空间大小,是在链接时确定的,并且分配在 sram 上,而不是 dram,因为 Nuttx 专为资源受限的嵌入式系统设计,从这一点就能看出来。
在这里插入图片描述
来看其弱函数的实现,有几个关键点:

  • g_idle_topstack:堆的起始地址,等会儿分析
  • 如果定义了 CONFIG_MM_KERNEL_HEAP,用户堆的起始地址需往上偏移 CONFIG_MM_KERNEL_HEAPSIZE,可参考上篇 blog 40、【OS】【Nuttx】【OSTest】内存监控:用户堆内存函数
  • heao_size:极限终点为 CONFIG_RAM_END,可见堆空间大小也是预先配置好的,程序运行时分配的堆空间不能超过配置值
    在这里插入图片描述
    g_idle_toptask 的定义如下,该定义描述了在 arm 中内存的结构分布
    在这里插入图片描述
    结构分布如下:
    在这里插入图片描述
    堆的位置在 g_top_stack 的上面,那栈的位置呢?当然是 g_top_stack 的下面,所以栈越界会怎么样?会将堆空间的内容给踩掉,造成程序的未定义行为。此处可对比之前 blog 22、【OS】【Nuttx】【最小系统】任务创建 里面 SIM 环境中关于栈空间的分配
    在这里插入图片描述
    这篇就讲到这里,下篇继续

http://www.mrgr.cn/news/94630.html

相关文章:

  • 基于Python的selenium入门超详细教程(第2章)--单元测试框架unittest
  • 图解多头注意力机制:维度变化一镜到底
  • 数据库的高阶知识
  • HTB 学习笔记 | 《Web应用安全从入门到精通》P5
  • 热key探测技术架构设计与实践
  • 【Agent】OpenManus-Tool 详细分析
  • 嵌入式SDIO 总线面试题及参考答案
  • 编程题-第k个语法符号
  • 树莓派 连接 PlutoSDR 教程
  • C++学习之二叉树
  • 深入理解 JVM 的垃圾收集器:CMS、G1、ZGC
  • Linux mount和SSD分区
  • 《AI大模型趣味实战》No2 : 快速搭建一个漂亮的AI家庭网站-相册/时间线/日历/多用户/个性化配色(中)
  • 五大基础算法——枚举算法
  • IT电子书的网站整理
  • go数据结构笔记
  • Netty基础—6.Netty实现RPC服务一
  • 【AI News | 20250316】每日AI进展
  • 新手村:数据预处理-异常值检测方法
  • 加固脱壳技术:DEX动态加载对抗