FreeRTOS学习(3)(运行底层)
摘要:文章主要讲解了堆和栈的区别及其在程序运行中的作用。栈由编译器自动管理,存放局部变量和函数调用信息,分配速度快但空间有限;堆需手动管理,适合动态内存分配但可能产生碎片。在FreeRTOS中,每个任务需要独立的栈空间来保存任务现场和临时变量。通过LED闪烁程序示例,说明了多任务切换时栈空间的重要性——虽然程序看似同时运行,实际上是快速切换执行,依赖各自的栈空间保存运行状态。
对于上一课的底层逻辑继续学习
为了进一步了解,底层处理逻辑再了解一下堆和栈
文章主要讲解了堆和栈的区别及其在程序运行中的作用。
栈(Stack)
自动管理:由编译器自动分配和释放
存储内容:局部变量、函数参数、返回地址等
堆(Heap)
动态内存区域
手动管理:程序员负责分配和释放
存储内容:动态分配的内存存储一些数组,动态内存等
栈从上到下分布
堆从下到上分布
下面用一个图来展现一下
再进入第一个函数之前,会把返回地址保存在LR寄存器里再跳转,但是再进入下一个内部函数时候会把这个地址保存到栈里
这一片内容很少主要是补充一下前面上一级却少的
| 特性 | 栈(Stack) | 堆(Heap) |
|---|---|---|
| 管理方式 | 编译器自动管理 | 程序员手动管理 |
| 分配速度 | 快(指针移动) | 慢(寻找合适块) |
| 释放方式 | 自动(函数返回) | 手动(free/delete) |
| 内存碎片 | 无 | 可能产生碎片 |
| 大小限制 | 较小(通常MB级) | 较大(受系统内存限制) |
| 访问方式 | 直接(CPU指令) | 间接(通过指针) |
| 线程安全 | 每个线程有独立栈 | 所有线程共享堆 |
| 数据寿命 | 函数/作用域内 | 直到显式释放 |
| 典型用途 | 局部变量、函数调用 | 动态数据结构、大对象 |
那么为什么每一个FreeRTOS任务都要有一个属于自己的栈空间
接着用前面的小灯程序解释
void MyTask(void *argument)
{
while(1)
{
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_0);
vTaskDelay(500);
}
}
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;)
{
HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
osDelay(1000);
}
/* USER CODE END StartDefaultTask */
}
这的程序到底是怎运行的呢
一个格子是500ms

每次值运行一个最小时间片(这个概念可以去看前面的内容),
再中间机器内部要来回不断计时,每一次要再两个程序来回跑来抛去,一次只停留一个最小时间片的时间来计时,因为程序足够快就达到了,同时运行两个函数的状态,再跑的过程中,他要保存任务现场,所以需要自己的内存,因这些其实本质上都是函数内部的临时变量(但是一直再用),所以要放在栈空间里。
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)