棧和棧幀

【摘自Linux/Unix系統編程手冊】編程

 

函數的調用和返回使棧的增加和收縮呈線性。X86-32體系架構上的Linux(和大多數其它Linux和Unix的實現),棧駐留在內存的高端並向下增加(朝堆的方向)。專用寄存器--棧指針(stack pointer),用於跟蹤當前棧頂。每次調用函數時,會在棧上新分配一幀,每當函數返回時,再從棧上將此幀移去。架構

雖然棧向下增加,但仍將棧的增加端稱爲棧頂,由於抽象地來講,狀況本就如此。棧的實際增加方向是個屬於硬件範疇的實現細節。在HP PA-RISC的Linux實現中,棧的增加方向就是向上的。函數

就虛擬內存而言,分配棧幀後,棧段的大小將會增加,但在大多數Linux實現中,釋放這些棧幀後,棧的大小並未減小(在分配新的棧幀時,會對這些內存從新加以利用)。當談論棧段的增加和收縮時,只是從邏輯視角來看待棧幀在棧中的增減狀況。指針

 

有時,會用用戶棧(user stack)來表示此處所討論的棧,以便與內核棧區分開來。內核棧是每一個進程保留在內核內存中的內存區域,在執行系統調用的過程當中供(內核)內部函數調用使用。(因爲用戶棧駐留在不受保護的用戶內存中,因此內核沒法利用用戶棧來達成這一目的)遞歸

 

每一個(用戶)棧幀包括以下內容:進程

  • 函數實參和局部變量:因爲這些變量都是在調用函數時自動建立的,所以在C語言中稱其爲自動變量。函數返回時將自動銷燬這些變量(由於棧幀會被釋放),這也是自動變量和靜態(以及全局)變量主要的語義區別:後者與函數執行無關,且長期存在。
  • 函數調用的連接信息:每一個函數都會用到一些CPU寄存器,好比程序計數器,其指向下一條將要執行的機器語言指令。每當一函數調用另外一函數時,會在被調用函數的棧幀中保存這些寄存器的副本,以便函數返回時能爲函數調用者將寄存器恢復原狀。

由於函數可以嵌套調用,因此棧中可能有多個棧幀(若一函數遞歸調用自身,則函數在棧中將有多個棧幀)。內存

相關文章
相關標籤/搜索