1. 程式人生 > >Linux應用程式地址分佈

Linux應用程式地址分佈

 (1)記憶體組成



 (2)記憶體佈局


 Linux所有應用程式都是從0x80480000開始,

其中0x80480000是一個虛擬地址


 1)下面來測試一下應用程式的地址分佈

#include <stdio.h>
#include <stdlib.h>

int global_init_a=1; //全域性的,初始化的變數 : 資料段
int global_uninit_a; //全域性的,沒有初始化的變數 : 資料段
static int static_global_init_a = 1; //全域性的,靜態的,初始化的變數 : 資料段
static int static_global_uninit_a; //全域性的,靜態的,未初始化的變數 : 資料段
const int const_global_a = 1; //全域性的,常量
: 程式碼段

int global_init_b=1; //全域性的,初始化的變數 : 資料段
int global_uninit_b; //全域性的,沒有初始化的變數 : 資料段
static int static_global_init_b = 1; //全域性的,靜態的,初始化的變數 : 資料段
static int static_global_uninit_b; //全域性的,靜態的,未初始化的變數 : 資料段
const int const_global_b = 1; //全域性的,常量 : 程式碼段

int main(void)
{
int local_init_a=1;
//區域性的,初始化的變數  : 棧
int local_uninit_a; //區域性的,沒有初始化的變數 : 棧
static int static_local_init_a = 1; //區域性的,靜態的,初始化的變數 : 資料段
static int static_local_uninit_a; //區域性的,靜態的,未初始化的變數 : 資料段
const int const_local_a = 1; //區域性的,常量 : 棧

int local_init_b=1; //區域性的,初始化的變數 : 棧
int local_uninit_b;
//區域性的,沒有初始化的變數 : 棧
static int static_local_init_b = 1; //區域性的,靜態的,初始化的變數 : 資料段
static int static_local_uninit_b; //區域性的,靜態的,未初始化的變數 : 資料段
const int const_local_b = 1; //區域性的,常量 : 棧

int * malloc_p_a; //區域性的,指標
malloc_p_a=malloc(sizeof(int)); //通過malloc分配得到的,區域性 : 堆

printf(“&global_init_a=%p, global_init_a=%d\n”,&global_init_a,global_init_a);
printf(“&global_uninit_a=%p, global_uninit_a=%d\n”,&global_uninit_a,global_uninit_a);
printf(“&static_global_init_a=%p, static_global_init_a=%d\n”,&static_global_init_a,static_global_init_a);
printf(“&static_global_uninit_a=%p, static_global_uninit_a=%d\n”,&static_global_uninit_a,static_global_uninit_a);
printf(“&const_global_a=%p, const_global_a=%d\n”,&const_global_a,const_global_a);

printf(“&global_init_b=%p, global_init_b=%d\n”,&global_init_b,global_init_b);
printf(“&global_uninit_b=%p, global_uninit_b=%d\n”,&global_uninit_b,global_uninit_b);
printf(“&static_global_init_b=%p, static_global_init_b=%d\n”,&static_global_init_b,static_global_init_b);
printf(“&static_global_uninit_b=%p, static_global_uninit_b=%d\n”,&static_global_uninit_b,static_global_uninit_b);
printf(“&const_global_b=%p, const_global_b=%d\n”,&const_global_b,const_global_b);

printf(“&local_init_a=%p, local_init_a=%d\n”,&local_init_a,local_init_a);
printf(“&local_uninit_a=%p, local_uninit_a=%d\n”,&local_uninit_a,local_uninit_a);
printf(“&static_local_init_a=%p, static_local_init_a=%d\n”,&static_local_init_a,static_local_init_a);
printf(“&static_local_uninit_a=%p, static_local_uninit_a=%d\n”,&static_local_uninit_a,static_local_uninit_a);
printf(“&const_local_a=%p, const_local_a=%d\n”,&const_local_a,const_local_a);

printf(“&local_init_b=%p, local_init_b=%d\n”,&local_init_b,local_init_b);
printf(“&local_uninit_b=%p, local_uninit_b=%d\n”,&local_uninit_b,local_uninit_b);
printf(“&static_local_init_b=%p, static_local_init_b=%d\n”,&static_local_init_b,static_local_init_b);
printf(“&static_local_uninit_b=%p, static_local_uninit_b=%d\n”,&static_local_uninit_b,static_local_uninit_b);
printf(“&const_local_b=%p, const_local_b=%d\n”,&const_local_b,const_local_b);

printf(“malloc_p_a=%p, malloc_p_a=%d\n”,malloc_p_a,*malloc_p_a);

while(1)
;

return 0;
}

 2) 編譯並執行程式,這裡不過多介紹


 3) 另開起一個終端

     ps -axu 檢視系統所有程序,找到我們剛才執行的程式./addr

     cat /proc/程序PID/maps 檢視記憶體分佈情況

 結果如下:



兩張圖的地址段對比就可以知道程式中的變數在記憶體中如何存放的!

已經將對比的結果寫到程式的註釋中了.

 

4)BSS段去哪裡了?

   1>首先檢視程式的格式 file addr

由此可知應用程式addr是elf屬性的檔案

    2> 使用readelf -S addr 來檢視bss的地址段


 由此可知BSS(未初始化的資料段):

全域性未初始化的變數(靜態的,非靜態的)

區域性未初始化的變數(靜態的)

另一種方法:(就是麻煩點微笑)

先判斷出所有變數的分佈,再找出未初始化的資料段的變數,即屬於BSS段


 5) 總結:

  5. BSS段: 

全域性未初始化的變數(靜態的,非靜態的)

區域性未初始化的變數(靜態的)







 (1)記憶體組成



 (2)記憶體佈局


 Linux所有應用程式都是從0x80480000開始,

其中0x80480000是一個虛擬地址


 1)下面來測試一下應用程式的地址分佈

#include <stdio.h>