linux代碼段,數據段,BSS段, 堆,棧

 linux代碼段,數據段,BSS段, 堆,棧


網上摘抄了一些,自己組織好了,以便參考 !!!! 


進 程(執行的程序)會佔用一定數量的內存,它或是用來存放從磁盤載入的程序代碼,或是存放取自用戶輸入的數據等等。不過進程對這些內存的管理方式因內存用途不一而不盡相同,有些內存是事先靜態分配和統一回收的,而有些卻是按需要動態分配和回收的。對任何一個普通進程來講,它都會涉及到5種不同的數據段(如代碼段,數據段,BSS段,堆段,棧段)。在進程被載入內存中時,基本上被分裂成主要的6個小的節(section)---如, .text節, .data節, .bss節, 堆節, 棧節, 環境/參數節.

 

 

一、Linux進程的五個段

下面我們來簡單歸納一下進程對應的內存空間中所包含的5種不同的數據區都是幹什麼的。

 

重點:

代碼段、數據段、堆棧段,這是一個概念
堆、棧、全局區、常量區,這是另一個概念

 

 

1)代碼段:代碼段是用來存放可執行文件的操作指令,也就是說是它是可執行程序在內存中的鏡像。代碼段需要防止在運行時被非法修改,所以只准許讀取操作,而不允許寫入(修改)操作——它是不可寫的代碼段(code segment/text segment)通常是指用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行前就已經確定,並且內存區域通常屬於只讀, 某些架構也允許代碼段爲可寫,即允許修改程序。在代碼段中,也有可能包含一些只讀的常數變量,例如字符串常量等。

 

2)數據段:數據段用來存放可執行文件中已初始化全局變量,換句話說就是存放程序靜態分配的變量和全局變量。

 

3BSS段:BSS段包含了程序中未初始化的全局變量,在內存中 bss段全部置零。BSS段(bss segment)通常是指用來存放程序中未初始化的全局變量的一塊內存區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬於靜態內存分配。

 

4)堆(heap):堆是用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)

它的物理內存空間是由程序申請的,並由程序負責釋放。

 

5)棧:棧又稱堆棧,棧是用戶存放程序臨時創建的局部變量,也就是說我們函數括弧“{}中定義的變量(但不包括static聲明的變量,static意味着在數據段中存放變量)。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,並且待到調用結束後,函數的返回值也會被存放回棧中。由於棧的先進先出特點,所以棧特別方便用來保存/恢復調用現場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數據的內存區。

   它是由操作系統分配的,內存的申請與回收都由OS管理。

 

舉個具體的C語言的例子吧:

//main.c

int a = 0; //全局初始化區

char *p1; //全局未初始化區

main()

{

static int c =0 //全局(靜態)初始化區

int b; //

char s[] = "abc"; //

char *p2; //

char *p3 = "123456"; //"123456\0"在常量區,p3在棧上。

p1 = (char *)malloc(10);

p2 = (char *)malloc(20); //分配得來得1020字節的區域就在堆區。

}

 

 

二、各個段在內存中的組織

各個段段在線性空間中的組織。直接上圖:

+--------------------------------   高地址

+ envstrings 環境變量字串    

+--------------------------------

+ argv string 命令行字串        

+--------------------------------

 

+ env pointers 環境變量指針表

+--------------------------------

+ argv pointers命令行參數指針表

+--------------------------------

+ argc 命令行參數個數

+--------------------------------

 

+     main函數的棧幀  

+--------------------------------

+     被調用函數的棧幀

+--------------------------------

+         ......                

+--------------------------------



+       (heap)                

+--------------------------------



+ BSS 未初始化全局數據     

+--------------------------------



+   Data 初始化的全局數據    

+--------------------------------

 

+   Text 代碼段                 

+--------------------------------   

其中,HeapBSSData這三個段在物理內存中是連續存放的,可以這麼理解:這三個是一體的。TextStack是獨立存放的,這是現在Linux中個段的分佈,0.11中代碼段和數據段不是分立的,是在一起的也就是說數據段和代碼段是一個段,當然了,堆與BSS也與它們一起了。從0.11的task_struct中還可以看出數據段、堆棧段的描述符是一個,都在ldt[2]處。

 

上圖是進程的虛擬地址空間示意圖。

堆棧段:

  1. 爲函數內部的局部變量提供存儲空間。

  2. 進行函數調用時,存儲“過程活動記錄”。

  3. 用作暫時存儲區。如計算一個很長的算術表達式時,可以將部分計算結果壓入堆棧。

數據段(靜態存儲區):

  包括BSS段的數據段,BSS段存儲未初始化的全局變量、靜態變量。數據段存儲經過初始化的全局和靜態變量。

代碼段:

  又稱爲文本段。存儲可執行文件的指令。

堆:

  就像堆棧段能夠根據需要自動增長一樣,數據段也有一個對象,用於完成這項工作,這就是堆(heap)。堆區域用來動態分配的存儲,也就是用 malloc 函數活的的內存。calloc和realloc和malloc類似。前者返回指針的之前把分配好的內存內容都清空爲零。後者改變一個指針所指向的內存塊的大小,可以擴大和縮小,他經常把內存拷貝到別的地方然後將新地址返回。

 

 

 

代碼段、數據段、堆棧段,這是一個概念
堆、棧、全局區、常量區,這是另一個概念

 

1、棧區(stack):由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。 

2、堆區(heap):由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表。 

3、全局區(靜態區):全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。 程序結束後由系統釋放。 

4、文字常量區:常量字符串就是放在這裏的。 程序結束後由系統釋放。 

5、程序代碼區:存放函數體的二進制代碼。

 

 

 

在進程被載入內存中時,基本上被分裂成許多小的節(section)。我們比較關注的是6個主要的節:

(1) .text 節
    .text 節基本上相當於二進制可執行文件的.text部分,它包含了完成程序任務的機器指令。該節標記爲只讀,如果發生寫操作,會造成segmentation fault。在進程最初被加載到內存中開始,該節的大小就被固定。

(2).data 節
      .data節用來存儲初始化過的變量,如:int a =0 ; 該節的大小在運行時固定的。

(3).bss 節
    棧下節(belowstack section ,即.bss)用來存儲爲初始化的變量,如:int a; 該節的大小在運行時固定的。

(4) 堆節
    堆節(heapsection)用來存儲動態分配的變量,位置從內存的低地址向高地址增長。內存的分配和釋放通過malloc() 和 free() 函數控制。

(5) 棧節

    棧節(stacksection)用來跟蹤函數調用(可能是遞歸的),在大多數系統上從內存的高地址向低地址增長。
同時,棧這種增長方式,導致了緩衝區溢出的可能性。

(6)環境/參數節
   環境/參數節(environment/argumentssection)用來存儲系統環境變量的一份複製文件,進程在運行時可能需要。例如,運行中的進程,可以通過環境變量來訪問路徑、shell 名稱、主機名等信息。該節是可寫的,因此在格式串(format string)和緩衝區溢出(buffer overflow)攻擊中都可以使用該節。
另外,命令行參數也保持在該區域中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章