由記憶體分割槽引發對堆疊的思考

2021-09-10 12:35:49 字數 2183 閱讀 6593

前言:

在c語言程式設計中,程式中的不同**和資料在編譯或者執行時處於ram的不同位置,是大家熟悉的記憶體分割槽的概念。

1.stm32f769晶元內的sram整體分割槽情況

**區和常量區是唯讀,在執行過程中是不能進行寫操作的,可以將其放在nor flash中,而棧區、堆區、全域性區中的資料是可讀可寫,而且在執行過程中需要進行讀寫操作的,所以一般放在sram中執行。

2. 棧區、堆區的區別

2.1 分配方式不同

棧區(stack)由編譯器自動分配釋放 ,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧;堆區(heap) 一般由程式設計師分配釋放, 若程式設計師不釋放,程式結束時可能由os** 。注意它與資料結構中的堆是兩回事,分配方式倒是類似於鍊錶。

2.2 生長方式不同

棧區(stack)一般是在編譯階段確定棧區的起始位址以及大小,入棧時棧頂指標向下生長(位址從高到低),所以一般來說棧的起始位址在sram的高位址;堆區(heap)是在執行時動態的選取記憶體區域,且為向上生長(位址從低到高)。

2.3 生命週期不同

棧區(stack)內儲存的函式區域性變數在函式返回時就自動丟失了,該區域可供下一次入棧的資料占用;堆區(heap)內的資料需要程式設計師手動進行釋放,否則會產生記憶體洩漏(所謂記憶體洩漏,俗氣一點就是:佔著茅坑不拉屎—浪費資源)。

總之,棧是靜態的,是編譯器所決定的;堆是動態的,是程式設計師自己來決定的。

而這裡的棧是指的函式棧,那麼和作業系統中的任務堆疊一樣不呢????

3.函式堆疊與任務堆疊

首先應該需要知道任務由什麼構成?任務是怎樣切換的以及切換過程對棧的操作?

3.1 任務的構成(以ucosii為例)

ucos-ii中的任務由任務堆疊、任務控制塊和任務**三部分所組成,其每部分具體作用如下:

任務堆疊—任務堆疊是用來儲存乙個任務執行時cpu的一些暫存器裡面存放的一些資料等。

任務控制塊—任務控制塊簡單來講就是結構體,它結構體裡面記錄的內容是任務的堆疊指標、任務的當前狀態、任務的優先級別和任務的等待延遲時間等一些任務的基本資訊。

任務**—這個就很容易理解了,就是具體任務執行的**程式。

3.2 任務切換

每個任務都需要分配乙個記憶體空間,這個記憶體空間作為任務堆疊,在任務執行時使用。

先說單任務情況,給該任務分配乙個記憶體空間作為任務棧,假設在乙個時候程式暫停,再執行任務時,仍然可以接著剛才停之前執行處繼續執行,為啥呢?因為在停的時候該任務棧儲存了所有該任務被中斷時的暫存器資料等資訊,再回來時可以繼續執行。

換到多工,每次執行**cpu是不會關心是什麼任務,它只會根據當前指令和棧裡的資訊執行而已。試想一下,乙個任務執行的時候被打斷,再次返回時棧裡的資訊不變,它是不是可以按照被打斷前那樣繼續執行?這個過程其實就是在恢復現場。

多工切換的實質是:作業系統控制sp暫存器中的值指向下乙個執行任務的堆疊位址,從而將cpu的執行環境帶到該任務的資料中,進而執行該任務。所以任務堆疊的意義是???

3.3 任務堆疊的意義

任務堆疊是為了實現程序間的切換時,將暫存器的資料儲存在堆疊中,一切都是cpu需要保護現場,跳走後還能正確返回。(補充:lr鏈結暫存器的目的也是儲存pc跳轉時的位址,為了執行完跳轉的程式後還能正確返回並繼續執行)

3.4 函式堆疊與任務堆疊的區別

1).函式堆疊和ucos的任務堆疊空間不是同一回事,ucos的任務堆疊空間是屬於全域性資料,存放在靜態區,而函式堆疊是在棧區,靜態區和棧區屬於同乙個級別,都是從ram分配。

2).函式堆疊是靜態的,由編譯器通過一些配置檔案自動生成,主要是編譯器完成,使用者是不需要也沒有必要去操作; 任務堆疊是作業系統的核心**的一部分,由作業系統設計者採用彙編或c語言實現。 函式堆疊是為了實現函式之間的呼叫時儲存區域性變數,任務堆疊是為了實現程序間的切換時儲存現場資料。

由 引發的思考

前陣子在乙個移動專案中,通過 的方式 繫結click 事件來提交乙個表單,由於表單資訊比較敏感,於是採用的post 同步提交的方式,原本到也沒有什麼。後來萬惡的pm說 你這個按鈕呀,要固定在底部比較好 於是乎就通過 position fixed 固定到底部了。那麼,問題來了 在ios 下,虛擬鍵盤是...

由flash引發對ARM架構的思考

前言 1.stm32f7 x系統架構 帶著整體的框架結構去看問題 分析問題會清晰一些,首先了解一下系統結構 圖1.1 2.nor flash為什麼可以執行 這句話分解一下有三點 什麼是執行?什麼是nor flash?為什麼可以執行?2.1.先了解下什麼是執行?這裡的執行並不是指真正的 執行 的概念,...

由XML Literal引發的思考

首先,什麼是xml literal呢?原來,這是在vb.net 9.0才引入的乙個用於構建xml物件的新特性,並且只有vb.net 9.0才支援。我們都知道,要建立xml樹,可以使用linq中的api,如下所示 出自vb.net 9.0 xml literal dim xml2 new xeleme...