news 2026/6/10 15:35:08

RTOS内核对象说明

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
RTOS内核对象说明

队列·,互斥锁,信号量都存储了RTOS的堆里面,RTOS通常只有一个全局堆,堆是程序员显示申请和释放的(malooc),内存空间是不连续的;

栈是编译器自动申请和释放的,函数执行完栈清除,第二次要执行的时候栈空间恢复,A函数调用B函数,B函数的栈空间要被A包含,栈空间是连续的。

全局静态区是存放全局变量和static修饰的变量。

这个函数里面malloc申请堆变量,函数结束时局部变量b指针会被清除,但b指向的地址不会被清除,后续这个地址就被浪费了。可以在函数结束前加入return b;然后在free(b);

void A() { int *b = (int*)malloc(sizeof(int)); // 堆分配 *b = 200; printf("*b = %d\n", *b); // 输出: *b = 200 // 函数结束,但malloc的内存没有被释放!❌ // 内存泄漏:丢失了指向分配内存的指针 }
// 或者返回指针给调用者管理 int* create_int() { int *b = (int*)malloc(sizeof(int)); *b = 400; return b; // 调用者负责释放 } void test() { int *ptr = create_int(); printf("%d\n", *ptr); free(ptr); // 调用者负责释放 }

在 RTOS (如 FreeRTOS) 中的关键点:​

  • ​多栈:​​ 每个任务都有自己的独立栈。这是任务独立运行的基础。任务栈大小是任务创建的关键参数。

  • ​共享堆:​​ 通常只有一个全局堆 (由 FreeRTOS 的heap_x.c实现管理,如heap_4.c)。所有动态内存分配 (包括动态创建的内核对象) 都来自这个堆。

  • ​内核对象内存来源:​​ 动态创建的队列、信号量、任务等,其结构体本身和存储区 (如队列的数据区、任务的栈) 都从堆中分配 (pvPortMalloc)。静态创建的对象则使用开发者预定义的全局/静态内存。

  • ​任务通知:​​ 其数据 (ulNotifiedValue,ucNotifyState) 存储在任务的 TCB 中。TCB 本身在堆 (动态任务) 或开发者静态内存 (静态任务) 中,​​不在​​任务栈上。

我们程序在执行的时候是硬件自动将数据放入cache里面,cpu只管从cache里面读数据即可。

内存的主要区域划分:​

  1. ​全局/静态区 (Data Segment): ​static和全局变量

    • ​初始化数据段 (Data Segment):​​ 存放​​已初始化​​的全局变量和静态变量(static修饰的局部变量也属于此类)。

    • ​未初始化数据段 (BSS Segment - Block Started by Symbol):​​ 存放​​未初始化​​或​​初始化为 0​​ 的全局变量和静态变量。操作系统在程序加载时会将其清零。

    • ​特性:​​ 生命周期贯穿整个程序运行。大小在编译/链接时确定。

  2. ​栈区 (Stack Segment):​

    • ​存放什么:​​ 函数调用时的局部变量、函数参数、返回地址、保存的寄存器上下文等。

    • ​管理方式:​​ ​​由编译器和硬件(栈指针寄存器 SP)自动管理​​。函数调用时自动分配(压栈),函数返回时自动释放(弹栈)。

    • ​特性:​

      • ​LIFO (后进先出):​​ 严格遵循调用顺序。

      • ​速度快:​​ 分配/释放只是移动栈指针。

      • ​空间连续:​​ 栈空间是连续的。

      • ​大小固定:​​ 在 RTOS 中,​​每个任务在创建时 (xTaskCreate) 就分配了固定大小的栈空间​​。usStackDepth参数决定了这个大小(单位通常是字,如configSTACK_DEPTH_TYPE定义的字长)。

      • ​风险:​​ ​​栈溢出 (Stack Overflow)​​ 是严重错误,发生在使用的栈空间超过分配的大小时。

  3. ​堆区 (Heap Segment):​

    • ​存放什么:​​ ​​动态分配​​的内存。例如:

      • 通过malloc(),calloc(),realloc()(C) /new(C++) 申请的内存。

      • 在 FreeRTOS 中,通过pvPortMalloc()申请的内存。

      • ​动态创建的 RTOS 内核对象​​(队列、信号量、互斥锁、事件组、动态任务的任务控制块 TCB 和任务栈)占用的内存也来自堆。

    • ​管理方式:​

      • ​显式申请:​​ 程序员必须​​显式调用​​分配函数 (malloc,pvPortMalloc,new)。

      • ​显式释放:​​ 程序员必须​​显式调用​​释放函数 (free,vPortFree,delete)。忘记释放会导致 ​​内存泄漏 (Memory Leak)​​。

      • ​非自动:​​ 堆内存的生命周期​​不​​与任何函数或代码块绑定,从分配成功开始,到显式释放结束。

    • ​特性:​

      • ​全局共享:​​ 所有任务、中断(需谨慎使用)都可以申请堆内存。

      • ​大小可变:​​ 运行时按需申请不同大小的内存块(受总堆大小限制)。

      • ​空间不连续:​​ 分配的内存块地址​​不一定连续​​。频繁分配释放不同大小的块会导致 ​​内存碎片化 (Fragmentation)​​,即使总空闲空间足够,也可能无法分配出连续的大块内存。

      • ​速度相对慢:​​ 分配和释放需要查找合适的内存块、更新管理数据结构(如空闲链表),比栈操作慢。

      • ​风险:​​ 内存泄漏、碎片化、分配失败 (malloc/pvPortMalloc返回NULL)。

rtos内核对象的存储位置:

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/10 15:33:21

GitHub Safe-Settings完整指南:从零开始配置仓库设置即代码

GitHub Safe-Settings完整指南:从零开始配置仓库设置即代码 【免费下载链接】safe-settings 项目地址: https://gitcode.com/gh_mirrors/sa/safe-settings GitHub Safe-Settings是一款强大的策略即代码(Policy-as-Code)工具&#xff…

作者头像 李华
网站建设 2026/6/10 15:31:22

Flask-Sockets完全指南:如何在Flask应用中优雅实现WebSocket通信

Flask-Sockets完全指南:如何在Flask应用中优雅实现WebSocket通信 【免费下载链接】flask-sockets [DEPRECATED] Alternative: https://github.com/miguelgrinberg/flask-sock 项目地址: https://gitcode.com/gh_mirrors/fl/flask-sockets Flask-Sockets是一个…

作者头像 李华
网站建设 2026/6/10 15:24:29

Chromium 源码剖析:base::NoDestructor——更安全的静态单例解决方案

C 静态对象的析构顺序是一个经常踩坑的话题,尤其是在 Chromium 这种超大工程里。先说结论:静态/全局对象的析构顺序与构造顺序相反(LIFO),但仅在同一个翻译单元(.cpp 文件)内有保证。跨翻译单元…

作者头像 李华
网站建设 2026/6/10 15:16:15

点亮0.96寸OLED之搬过来的代码,但是自己OLED不能亮

检查自己代码过程:while循环里面加了灯闪烁现象:OLED黑屏,但是灯闪烁原代码是:GPIO_Mode_Out_OD // 开漏输出修改成GPIO_Mode_Out_PP // 推挽输出OLED成功显示了开漏输出GPIO_Mode_Out_OD:引脚仅能拉低电平&#xff0c…

作者头像 李华
网站建设 2026/6/10 15:13:07

搜索与回溯

有重复元素的排列问题题目描述设R{r1,r2,……,rn}是要进行排列的n个元素。其中元素r1,r2,……,rn可能相同。使设计一个算法,列出R的所有不同排列。给定n以及待排列的n个元素。计算出这n个元素的…

作者头像 李华
网站建设 2026/6/10 15:11:14

5 种 AI 对话数据格式全解析

本文面向:想统一管理多个 AI 编程工具对话数据的开发者。 预计阅读时间:10 分钟 最终效果:理解 Claude Code、Codex、Cursor、Trae、Copilot 五种对话格式的结构、优劣与解析陷阱,明白为什么需要统一抽象层。 当你用 Claude Code …

作者头像 李华