進 程(執(zhí)行的程序)會占用一定數(shù)量的內(nèi)存,它或是用來存放從磁盤載入的程序代碼,或是存放取自用戶輸入的數(shù)據(jù)等等。不過進程對這些內(nèi)存的管理方式因內(nèi)存用途 不一而不盡相同,有些內(nèi)存是事先靜態(tài)分配和統(tǒng)一回收的,而有些卻是按需要動態(tài)分配和回收的。對任何一個普通進程來講,它都會涉及到5種不同的數(shù)據(jù)段。
一、Linux進程的五個段
下面我們來簡單歸納一下進程對應的內(nèi)存空間中所包含的5種不同的數(shù)據(jù)區(qū)都是干什么的。
1)代碼段:代碼段是用來存放可執(zhí)行文件的操作指令,也就是說是它是可執(zhí)行程序在內(nèi)存中的鏡像。代碼段需要防止在運行時被非法修改,所以只準許讀取操作,而不允許寫入(修改)操作——它是不可寫的。
2)數(shù)據(jù)段:數(shù)據(jù)段用來存放可執(zhí)行文件中已初始化全局變量,換句話說就是存放程序靜態(tài)分配的變量和全局變量。
3)BSS段:BSS段包含了程序中未初始化的全局變量,在內(nèi)存中 bss段全部置零。
4)堆(heap):堆是用于存放進程運行中被動態(tài)分配的內(nèi)存段,它的大小并不固定,可動態(tài)擴張或縮減。當進程調(diào)用malloc等函數(shù)分配內(nèi)存時,新分配的內(nèi)存就被動態(tài)添加到堆上(堆被擴張);當利用free等函數(shù)釋放內(nèi)存時,被釋放的內(nèi)存從堆中被剔除(堆被縮減)
它的物理內(nèi)存空間是由程序申請的,并由程序負責釋放。
5)棧:棧是用戶存放程序臨時創(chuàng)建的局部變量,也就是說我們函數(shù)括弧“{}”中定義的變量(但不包括static聲明的變量,static意味著在數(shù)據(jù)段中存放變量)。除此以外,在函數(shù)被調(diào)用時,其參數(shù)也會被壓入發(fā)起調(diào)用的進程棧中,并且待到調(diào)用結束后,函數(shù)的返回值也會被存放回棧中。由于棧的先進先出特點,所以棧特別方便用來保存/恢復調(diào)用現(xiàn)場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數(shù)據(jù)的內(nèi)存區(qū)。
它是由操作系統(tǒng)分配的,內(nèi)存的申請與回收都由OS管理。
舉個具體的C語言的例子吧:
//main.c
int a = 0; //全局初始化區(qū)
char *p1; //全局未初始化區(qū)
main()
{
static int c =0; //全局(靜態(tài))初始化區(qū)
int b; //棧
char s[] = "abc"; //棧
char *p2; //棧
char *p3 = "123456"; //"123456\0"在常量區(qū),p3在棧上。
p1 = (char *)malloc(10);
p2 = (char *)malloc(20); //分配得來得10和20字節(jié)的區(qū)域就在堆區(qū)。
}
二、各個段在內(nèi)存中的組織
各個段段在線性空間中的組織。直接上圖:
+-------------------------------- 高地址
+ envstrings 環(huán)境變量字串
+--------------------------------
+ argv string 命令行字串
+--------------------------------
+ env pointers 環(huán)境變量指針表
+--------------------------------
+ argv pointers命令行參數(shù)指針表
+--------------------------------
+ argc 命令行參數(shù)個數(shù)
+--------------------------------
+ main函數(shù)的棧幀
+--------------------------------
+ 被調(diào)用函數(shù)的棧幀
+--------------------------------
+ ......
+--------------------------------
+ 堆(heap)
+--------------------------------
+ BSS 未初始化全局數(shù)據(jù)
+--------------------------------
+ Data 初始化的全局數(shù)據(jù)
+--------------------------------
+ Text 代碼段
+--------------------------------
其中,Heap,BSS,Data這三個段在物理內(nèi)存中是連續(xù)存放的,可以這么理解:這三個是一體的。Text、Stack是獨立存放的,這是現(xiàn)在Linux中個段的分布,在0.11中代碼段和數(shù)據(jù)段不是分立的,是在一起的也就是說數(shù)據(jù)段和代碼段是一個段,當然了,堆與BSS也與它們一起了。從0.11的task_struct中還可以看出數(shù)據(jù)段、堆棧段的描述符是一個,都在ldt[2]處。