java数据段 静态区_linux进程的堆栈空间_代码段(指令,只读)、数据段(静态变量,全局变量)、堆栈段(局部变量)、栈【转】...
一)概述
.堆棧是一個用戶空間的內存區域,進程使用堆棧作為臨時存儲。
.堆棧中存放的是函數中的局部變量,在函數的生命周期中可以將變量壓入堆棧,編譯器需要確保堆棧指針在函數退出前恢復到初始位置,也就是說,內存是自動分配和釋放的,C/C++把存儲在堆棧中的局部變量當作automatic存儲,并使用auto關鍵字,這是局部變量的默認存儲方式,所以現在沒有人用auto關鍵詞.
.與動態存儲(auto)相對映的靜態存儲(static),也就是用static定義的局部變量,它不用堆棧來存儲,而是使用數據段來存儲(也就是說它的生命周期在整個程序運行期間)。
.堆棧的基地址位于用戶空間的最高虛擬地址附近,并從那里向下延伸。
.一個進程開始時,堆棧的最大值就不能改變,如果占用的空間超過了堆棧大小,那么就會導致堆棧溢出。
二)進程的內存組織形式
進程被分為三個區域:文本、數據和堆棧。
1)文本區域:
文本區域也叫做代碼段,是由程序確定的,
它包括代碼(指令)和只讀數據,該區域通常被標記為只讀,任何對其寫入的操作會導致段錯誤.
2)數據區域(靜態內存分配(static)):
數據區域也叫做數據段,
它包括已初始化和未初始化的數據,靜態變量存儲在這個區域中,它的大小可以用系統調用brk(2)來改變。
詳細了解數據區域:
分成初始化為非零的數據區、BSS和堆(Heap)三個區域。
初始化非零數據區域一般存放靜態非零數據和全局的非零數據,屬于靜態內存分配(全局變量,static修飾的變量);
BSS(Block Started by Symbol)區域(都初始化為0了)一般存放未初始化的全局數據(默認值為0)和未初始化的靜態數據(默認值為0),屬于靜態內存分配(全局變量、static修飾的變量);
堆區域一般存放運行時動態分配的內存空間,其大小不固定,可動態擴張或縮減。當調用malloc等函數分配內存時,新分配的內存被動態添加到堆上;當調用free等函數釋放內存時,被釋放內存從堆中被剔除。
代碼段和數據段之間有明確的分隔,
但是數據段和堆棧段之間沒有,而且棧是向下增長,堆是向上增長的,因此理論上堆和棧會“增長到一起”,操作系統的內存管理功能需要防止這樣的錯誤發生。
3)堆棧區域(動態內存分配auto,默認,所以不用關鍵字auto):
堆棧區域也叫堆棧段,
它用于給局部變量動態分配空間,同樣函數傳遞參數和函數返回值也要用到堆棧.
堆棧也可向下增長(向內存低地址)也可以向上增長,這依賴于具體的實現,
通常都是向下增長的,而SP(堆棧指針)也是指向堆棧的最后地址.
4)內存的分配區域:
根據前面所述,堆棧是位于最高虛擬地址附近,而數據段則位于堆棧段之后,最后是代碼段。
也就是:
低地址 代碼段 或 高地址 堆棧段
數據段 數據段
高地址 堆棧段 低地址 代碼段
三)堆棧著色
當兩個線程或進程使用相同的堆棧虛擬地址時,它們會爭奪同一個cache行,導致競爭和降級行為.
堆棧著色的技術使每一個進程的基址都不相同,通過隨機分配堆棧基址,多個進程會使用不同的cache行來避免.
四)堆棧的限制
堆棧空間的最大值是由setrlimit系統調用確定的,也可以通過bash內建的ulimit命令來設定和查看.
例如:
查看當前可使用的最大堆棧(以KB為單位)
ulimit -s
8192?//棧的大小默認是8M
設定為最大的使用堆棧為15KB
ulimit -s 15
此時執行ls將會得到一個段錯誤.
ls -l /etc/
total 1040
Segmentation fault
通過用strace跟蹤ls命令,將發現有如下的系統調用
getrlimit(RLIMIT_STACK, {rlim_cur=15*1024, rlim_max=15*1024}) = 0
說明當前可用的堆棧空間,已經不足以運行strace命令了.
五)常駐內存和鎖定內存
常駐內存專指存儲在RAM中的內存部分,不包括存儲在交換區和未存儲的進程的內存.
鎖定內存是常駐內存的子集,它指被進程明確地鎖定到RAM的虛擬內存中,不能用于交換,并一直常駐于RAM中.
總結
以上是生活随笔為你收集整理的java数据段 静态区_linux进程的堆栈空间_代码段(指令,只读)、数据段(静态变量,全局变量)、堆栈段(局部变量)、栈【转】...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1px 等于多少 pt(1em等于多少像
- 下一篇: 巫师3男爵的妻子在哪