目錄
? ? ? ?
#堆在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