目录
#堆在RTOS的概念
#相关代码表示
#堆相关特点
#栈在RTOS中的概念
#栈的代码表示
#栈的相关特点
#为什么每个RTOS任务都要有自己的栈
前言:本篇参考韦东山老师的RTOS,连接放在最后
#堆在RTOS的概念
本文所指的堆与栈并不是数据结构中,的堆与栈,实时操作系统(RTOS)中,堆(Heap)是一个动态内存分配区域,用于存储程序运行过程中大小未知或可变的数据结构。堆内存不像栈内存那样由操作系统自动管理,它是由程序员申请和释放的。用户可以根据需要请求一段连续的内存空间,并在程序执行过程中随着数据的变化而增长或减小。
堆与栈经常混着用,而栈是RTOS的基础,所为堆就是一块内存,我们可以管理内存,从内存中使用一部分,用完之后在把他释放回去。
#相关代码表示
代码里定义了heap_buf[1024]数组,作为内存空间,定义void *my_malloc(int size);这个函数在main()里面去使用,数组的内存空间,这个过程就是申请内存空间的堆,使用堆作为存储数据的存在,同样可以使用函数,对已经定义使用的,内存空间去进行释放。
char heap_buf[1024];//这里定义一个堆
int pos = 0;
void *my_malloc(int size);
int main()//主函数
{char ch = 65;char *buf = my_malloc(100);//调用函数占用内存unsigned char uch = 200;for(i = 0; i<26;i++)buf[i] = 'A'+i;return 0;
}
void *my_malloc(int size)//定义函数使用堆
{int old_pos = pos;pos+=size;return &heap_buf[old_pos];
}
#堆相关特点
动态分配:进程可以在运行时根据需要动态地向堆中申请内存,不需要预先指定固定大小。
无预定义大小:堆的大小没有固定限制,直到系统内存不足或者达到预设的内存阈值才会停止分配。
内存管理:程序员负责堆内存的分配和释放,如果忘记释放已不再使用的内存,可能导致内存泄漏。
性能开销:由于堆内存管理通常比栈内存复杂,可能会引入一定的性能开销,尤其是在频繁大块分配或回收时。
总结:堆是程序中的内存分配区域,用于存储变量等,这个空间由代码申请或者释放。
#栈在RTOS中的概念
栈在RTOS中非常重要,RTOS操作系统,没有文件功能,因为只有内核,仅支持多任务的要求,而栈也是一块内存空间,CPU的SP寄存器指向栈,可以用于函数调用·,局部变量,多任务系统保存现场空间。
#栈的代码表示
void a_func(volatile int a);//定义函数声明
void b_func(volatile int a);//定义函数声明
void c_func(volatile int a);//定义函数功能
int g_cnt = 0;//定义变量声明
int main()//主函数
{char ch = 65;char *buf = my_malloc(100);//调用函数占用内存unsigned char uch = 200;volatile int i = 99;for(i = 0; i<26;i++)buf[i] = 'A'+i;a_funct(i);return 0;
}
void a_func(volatile int a)//定义函数功能
{g_cnt = b_funct(a);c_funct(g_cnt);
}
void b_func(volatile int a)//定义函数功能
{a+=2;return a;
}
void c_func(volatile int a)//定义函数功能
{a+=2;return a;
}
void *my_malloc(int size)//定义函数使用堆
{int old_pos = pos;pos+=size;return &heap_buf[old_pos];
}
在这个程序里面,main()里面调用a_func ,a_func里面调用了b_func和c_func,这里面有一个层层调用的关系,对应的汇编代码如下。
main()里面a_func ,调用指令。在使用BL汇编指令,进行函数调用的时候,BL指令的功能是,LR=0x8000154,同时PC=0x8000154,这个地址就是调用函数a_func在寄存器中的地址,同时调用,在执行调用函数的时候,会保存返回地址,PUSH {r0,r1} 所以C语言调用函数的本质是使用BL指令main()函数中转跳执行函数的时候,下面一些语句还没有执行,需要执行,在执行完调用函数的时候就需要返回,转跳位置,重新进行执行。
在最后调用的函数c_func(),执行完之后,lr寄存器的值,会被弹出,里面保存的是a_func()函数的地址,从而跳转到c_func()被调用的地方,继续执行下面的语句,同理当a_func()执行完成的时候,lr寄存器里面的值保存的是main()里面a_func()跳转的部分,从而继续执行下面的语句。
在main()函数/自定义函数,的汇编语言中第一条语句,通常是保存 r0 r1 r2 r3 这些寄存器 LR返回地址 局部变量 这些数据会被保存RAM的栈中,在函数的调用结束之后,局部便令,LR在栈中分配的内存空间会被释放。
#栈的相关特点
在实时操作系统(RTOS)中,栈(Stack)是一个特殊的内存区域,主要用于存储程序执行过程中的局部变量、函数参数和函数调用的返回地址。它是按照后进先出(Last In, First Out,LIFO)的原则工作的,类似于生活中的堆叠物品。
每当程序进入一个新的函数或遇到递归调用时,系统会在栈顶分配空间来保存这些信息。当函数执行完毕并返回时,相关的数据会被弹出栈,以便让控制权回到调用该函数的地方。栈的空间大小通常是有限的,如果栈溢出(超过其预设的最大限制),可能会导致严重的运行时错误,甚至影响系统的稳定性。
RTOS中的任务调度和中断处理也常常利用栈,因为它们涉及快速响应和切换。每个任务或中断服务都会有自己的私有栈,这样即使在中断处理过程中,主任务的执行不会被打断,保证了操作的连续性和实时性。
#为什么每个RTOS任务都要有自己的栈
在RTOS环境下,有任务A和任务B,在多任务系统下,A与B切换运行,由定时器发生中断进行切换任务。
每次函数进行切换的时候,需要保存现场,恢复现场,指的是保存A函数的寄存器,恢复保存B函数的寄存器,这里(A函数切换B函数为例)反之,则相反。
这些保存的现场,保存的就是函数使用的寄存器,局部变量,LR,等等。这些数据会被保存在内存的栈的位置,所以说每一个任务都需要有自己的栈。
欢迎指正,最后希望对你有所帮助!!!
[3-3-2]_栈的概念_函数调用_哔哩哔哩_bilibili