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