成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux下C程序進(jìn)程地址空間布局

開發(fā) 后端
今天我們將從進(jìn)程地址空間中典型的存儲區(qū)域分配情況開始講起,然后順序到Linux下C程序進(jìn)程地址空間布局。

  我們在學(xué)習(xí)C程序開發(fā)時經(jīng)常會遇到一些概念:代碼段、數(shù)據(jù)段、BSS段(Block Started by Symbol) 、堆(heap)和棧(stack)。先看一張教材上的示意圖(來源,《UNIX環(huán)境高級編程》一書),顯示了進(jìn)程地址空間中典型的存儲區(qū)域分配情況。

從圖中可以看出:

從低地址到高地址分別為:代碼段、(初始化)數(shù)據(jù)段、(未初始化)數(shù)據(jù)段(BSS)、堆、棧、命令行參數(shù)和環(huán)境變量堆向高內(nèi)存地址生長棧向低內(nèi)存地址生長

  還經(jīng)常看到下面這個圖(來源,不詳):

先看一段程序。

  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. int global_init_a=1;   
  4. int global_uninit_a;   
  5. static int static_global_init_a=1;   
  6. static int static_global_uninit_a;   
  7. const int const_global_a=1;   
  8. int global_init_b=1;   
  9. int global_uninit_b;   
  10. static int static_global_init_b=1;   
  11. static int static_global_uninit_b;   
  12. const int const_global_b=1; /*上面全部為全局變量,main函數(shù)中的為局部變量*/ int main()     
  13. int local_init_a=1;     
  14. int local_uninit_a;     
  15. static int static_local_init_a=1;     
  16. static int static_local_uninit_a;     
  17. const int const_local_a=1;     
  18. int local_init_b=1;     
  19. int local_uninit_b;     
  20. static int static_local_init_b=1;     
  21. static int static_local_uninit_b;     
  22. const int const_local_b=1;     
  23. int * malloc_p_a;     
  24. malloc_p_a=malloc(sizeof(int));     
  25. printf(" &global_init_a=%p        
  26. global_init_a=%d ",&global_init_a,global_init_a);   
  27. printf(" &global_uninit_a=%p       
  28. global_uninit_a=%d ",&global_uninit_a,global_uninit_a);  
  29.  printf(" &static_global_init_a=%p       
  30. static_global_init_a=%d ",&static_global_init_a,static_global_init_a);  
  31.  printf("&static_global_uninit_a=%p     
  32. static_global_uninit_a=%d ",&static_global_uninit_a,static_global_uninit_a); 
  33.   printf(" &const_global_a=%p       
  34. const_global_a=%d ",&const_global_a,const_global_a);  
  35.  printf(" &global_init_b=%p       
  36. global_init_b=%d ",&global_init_b,global_init_b);  
  37.  printf(" &global_uninit_b=%p       
  38. global_uninit_b=%d ",&global_uninit_b,global_uninit_b); 
  39.  printf(" &static_global_init_b=%p    
  40.  static_global_init_b=%d ",&static_global_init_b,static_global_init_b); 
  41.   printf("&static_global_uninit_b=%p     
  42. static_global_uninit_b=%d ",&static_global_uninit_b,static_global_uninit_b);  
  43.  printf(" &const_global_b=%p       
  44. const_global_b=%d ",&const_global_b,const_global_b);     
  45. printf(" &local_init_a=%p       
  46. local_init_a=%d ",&local_init_a,local_init_a);     
  47. printf(" &local_uninit_a=%p       
  48. local_uninit_a=%d ",&local_uninit_a,local_uninit_a);  
  49.  printf(" &static_local_init_a=%p     
  50. static_local_init_a=%d ",&static_local_init_a,static_local_init_a);     
  51. printf(" &static_local_uninit_a=%p     
  52. static_local_uninit_a=%d ",&static_local_uninit_a,static_local_uninit_a);  
  53.  printf(" &const_local_a=%p       
  54. const_local_a=%d ",&const_local_a,const_local_a);     
  55. printf(" &local_init_b=%p       
  56. local_init_b=%d ",&local_init_b,local_init_b);     
  57. printf(" &local_uninit_b=%p       
  58. local_uninit_b=%d ",&local_uninit_b,local_uninit_b);   
  59. printf(" &static_local_init_b=%p       
  60. static_local_init_b=%d ",&static_local_init_b,static_local_init_b);    
  61.  printf(" &static_local_uninit_b=%p     
  62. static_local_uninit_b=%d ",&static_local_uninit_b,static_local_uninit_b);  
  63.  printf(" &const_local_b=%p      
  64.  const_local_b=%d ",&const_local_b,const_local_b);  
  65.  printf(" malloc_p_a=%p       
  66. *malloc_p_a=%d ",malloc_p_a,*malloc_p_a);     
  67. return 0; 

  下面是輸出結(jié)果。

  先仔細(xì)分析一下上面的輸出結(jié)果,看看能得出什么結(jié)論。貌似很難分析出來什么結(jié)果。好了我們繼續(xù)往下看吧。

  接下來,通過查看proc文件系統(tǒng)下的文件,看一下這個進(jìn)程的真實內(nèi)存分配情況。(我們需要在程序結(jié)束前加一個死循環(huán),不讓進(jìn)程結(jié)束,以便我們進(jìn)一步分析)。

  在return 0前,增加 while(1); 語句

  重新編譯后,運行程序,程序?qū)⑦M(jìn)入死循環(huán)。

使用ps命令查看一下進(jìn)程的pid

  #ps -aux | grep a.out

  查看/proc/2699/maps文件,這個文件顯示了進(jìn)程在內(nèi)存空間中各個區(qū)域的分配情況。

  #cat /proc/2699/maps

上面紅顏色標(biāo)出的幾個區(qū)間是我們感興趣的區(qū)間:

08048000-08049000 r-xp 貌似是代碼段08049000-0804a000 r--p 暫時不清楚,看不出來0804a000-0804b000 rw-p 貌似為數(shù)據(jù)段08a7e000-08a9f000 rw-p 堆bff73000-bff88000 rw-p 棧

  我們把這些數(shù)據(jù)與最后一次的程序運行結(jié)果進(jìn)行比較,看看有什么結(jié)論。

  &global_init_a=0x804a018 全局初始化:數(shù)據(jù)段 global_init_a=1
      &global_uninit_a=0x804a04c 全局未初始化:數(shù)據(jù)段 global_uninit_a=0
   &static_global_init_a=0x804a01c 全局靜態(tài)初始化:數(shù)據(jù)段 static_global_init_a=1
&static_global_uninit_a=0x804a038 全局靜態(tài)未初始化:數(shù)據(jù)段 static_global_uninit_a=0
       &const_global_a=0x80487c0 全局只讀變量: 代碼段 const_global_a=1

         &global_init_b=0x804a020 全局初始化:數(shù)據(jù)段 global_init_b=1
      &global_uninit_b=0x804a048 全局未初始化:數(shù)據(jù)段 global_uninit_b=0
   &static_global_init_b=0x804a024 全局靜態(tài)初始化:數(shù)據(jù)段 static_global_init_b=1
&static_global_uninit_b=0x804a03c 全局靜態(tài)未初始化:數(shù)據(jù)段 static_global_uninit_b=0
      &const_global_b=0x80487c4 全局只讀變量: 代碼段 const_global_b=1

         &local_init_a=0xbff8600c 局部初始化:棧 local_init_a=1
       &local_uninit_a=0xbff86008 局部未初始化:棧 local_uninit_a=134514459
   &static_local_init_a=0x804a028 局部靜態(tài)初始化:數(shù)據(jù)段 static_local_init_a=1
&static_local_uninit_a=0x804a040 局部靜態(tài)未初始化:數(shù)據(jù)段 static_local_uninit_a=0
       &const_local_a=0xbff86004 局部只讀變量:棧 const_local_a=1

         &local_init_b=0xbff86000 局部初始化:棧 local_init_b=1
        &local_uninit_b=0xbff85ffc 局部未初始化:棧 local_uninit_b=-1074241512
   &static_local_init_b=0x804a02c 局部靜態(tài)初始化:數(shù)據(jù)段 static_local_init_b=1
&static_local_uninit_b=0x804a044 局部靜態(tài)未初始化:數(shù)據(jù)段 static_local_uninit_b=0
        &const_local_b=0xbff85ff8 局部只讀變量:棧 const_local_b=1


  p_chars=0x80487c8 字符串常量:代碼段 p_chars=abcdef
          malloc_p_a=0x8a7e008 malloc動態(tài)分配:堆 *malloc_p_a=0

通過以上分析我們暫時可以得到的結(jié)論如下,在進(jìn)程的地址空間中

數(shù)據(jù)段中存放:全局變量(初始化以及未初始化的)、靜態(tài)變量(全局的和局部的、初始化的以及未初始化的)代碼段中存放:全局只讀變量(const)、字符串常量堆中存放:動態(tài)分配的區(qū)域棧中存放:局部變量(初始化以及未初始化的,但不包含靜態(tài)變量)、局部只讀變量(const)

  這里我們沒有發(fā)現(xiàn)BSS段,但是我們將未初始化的數(shù)據(jù)按照地址進(jìn)行排序看一下,可以發(fā)現(xiàn)一個規(guī)律。

  &global_init_a=0x804a018 全局初始化:數(shù)據(jù)段 global_init_a=1
  &static_global_init_a=0x804a01c 全局靜態(tài)初始化:數(shù)據(jù)段 static_global_init_a=1
        &global_init_b=0x804a020 全局初始化:數(shù)據(jù)段 global_init_b=1
  &static_global_init_b=0x804a024 全局靜態(tài)初始化:數(shù)據(jù)段 static_global_init_b=1
    &static_local_init_a=0x804a028 局部靜態(tài)初始化:數(shù)據(jù)段 static_local_init_a=1
    &static_local_init_b=0x804a02c 局部靜態(tài)初始化:數(shù)據(jù)段 static_local_init_b=1

&static_global_uninit_a=0x804a038 全局靜態(tài)未初始化:數(shù)據(jù)段 static_global_uninit_a=0
&static_global_uninit_b=0x804a03c 全局靜態(tài)未初始化:數(shù)據(jù)段 static_global_uninit_b=0
 &static_local_uninit_a=0x804a040 局部靜態(tài)未初始化:數(shù)據(jù)段 static_local_uninit_a=0
 &static_local_uninit_b=0x804a044 局部靜態(tài)未初始化:數(shù)據(jù)段 static_local_uninit_b=0
      &global_uninit_b=0x804a048 全局未初始化:數(shù)據(jù)段 global_uninit_b=0
      &global_uninit_a=0x804a04c 全局未初始化:數(shù)據(jù)段 global_uninit_a=0


  這里可以發(fā)現(xiàn),初始化的和未初始化的數(shù)據(jù)好像是分開存放的,因此我們可以猜測BSS段是存在的,只不過數(shù)據(jù)段是分為初始化和未初始化(即BSS段)的兩部分,他們在加載到進(jìn)程地址空間時是合并為數(shù)據(jù)段了,在進(jìn)程地址空間中沒有單獨分為一個區(qū)域。

  還有一個問題,靜態(tài)數(shù)據(jù)與非靜態(tài)數(shù)據(jù)是否是分開存放的呢?請讀者自行分析一下。

  接下來我們從程序的角度看一下,這些存儲區(qū)域是如何分配的。首先我們先介紹一下ELF文件格式。

ELF(Executable and Linkable Format )文件格式是一個開放標(biāo)準(zhǔn),各種UNIX系統(tǒng)的可執(zhí)行文件都采用ELF格式,它有三種不同的類型:–可重定位的目標(biāo)文件(Relocatable,或者Object File)–可執(zhí)行文件(Executable)–共享庫(Shared Object,或者Shared Library)下圖為ELF文件的結(jié)構(gòu)示意圖(來源,不詳):

  一個程序編譯生成目標(biāo)代碼文件(ELF文件)的過程如下,此圖引自《程序員的自我修養(yǎng)》一書的一個圖:

        

  可以通過readelf命令查看EFL文件的相關(guān)信息,例如 readelf -a a.out ,我們只關(guān)心各個段的分配情況,因此我們使用以下命令:

  # readelf -S a.out            

將這里的內(nèi)存布局與之前看到的程序的運行結(jié)果進(jìn)行分析:

  &global_init_a=0x804a018 全局初始化:數(shù)據(jù)段 global_init_a=1
      &global_uninit_a=0x804a04c 全局未初始化:BSS段 global_uninit_a=0
   &static_global_init_a=0x804a01c 全局靜態(tài)初始化:數(shù)據(jù)段 static_global_init_a=1
&static_global_uninit_a=0x804a038 全局靜態(tài)未初始化:BSS段 static_global_uninit_a=0
       &const_global_a=0x80487c0 全局只讀變量: 只讀數(shù)據(jù)段 const_global_a=1

         &global_init_b=0x804a020 全局初始化:數(shù)據(jù)段 global_init_b=1
      &global_uninit_b=0x804a048 全局未初始化:BSS段 global_uninit_b=0
   &static_global_init_b=0x804a024 全局靜態(tài)初始化:數(shù)據(jù)段 static_global_init_b=1
&static_global_uninit_b=0x804a03c 全局靜態(tài)未初始化:BSS段 static_global_uninit_b=0
      &const_global_b=0x80487c4 全局只讀變量: 只讀數(shù)據(jù)段 const_global_b=1

   &static_local_init_a=0x804a028 局部靜態(tài)初始化:數(shù)據(jù)段 static_local_init_a=1
&static_local_uninit_a=0x804a040 局部靜態(tài)未初始化:BSS段 static_local_uninit_a=0

   &static_local_init_b=0x804a02c 局部靜態(tài)初始化:數(shù)據(jù)段 static_local_init_b=1
&static_local_uninit_b=0x804a044 局部靜態(tài)未初始化:BSS段 static_local_uninit_b=0

              p_chars=0x80487c8 字符串常量:只讀數(shù)據(jù)段 p_chars=abcdef
ELF 文件一般包含以下幾個段 :

.text section:主要是編譯后的源碼指令,是只讀字段。.data section :初始化后的非const的全局變量、局部static變量。.bss:未初始化后的非const全局變量、局部static變量。.rodata字段 是存放只讀數(shù)據(jù)

  分析到這以后,我們在和之前分析的結(jié)果對比一下,會發(fā)現(xiàn)確實存在BSS段,地址為0804a030 ,大小為0x20,之前我們的程序中未初始化的的確存放在這個地址區(qū)間中了,只不過執(zhí)行exec系統(tǒng)調(diào)用時,將這部分的數(shù)據(jù)初始化為0后,放到了進(jìn)程地址空間的數(shù)據(jù)段中了,在進(jìn)程地址空間中就沒有必要存在BSS段了,因此都稱做數(shù)據(jù)段。同理,.rodata字段也是與text段放在一起了。

  在ELF文件中,找不到局部非靜態(tài)變量和動態(tài)分配的內(nèi)容。

【編輯推薦】
責(zé)任編輯:彭凡 來源: CSDN博客
相關(guān)推薦

2020-10-25 10:40:41

Windows

2020-10-22 10:26:37

Windows10

2012-05-03 08:27:20

Linux進(jìn)程

2011-01-18 10:00:59

Linux磁盤分區(qū)

2011-01-18 09:51:59

Linux磁盤分區(qū)

2011-01-18 10:25:19

Linux磁盤分區(qū)

2021-01-08 05:59:39

Linux應(yīng)用程序Linux系統(tǒng)

2019-01-28 18:05:04

2019-02-13 13:31:42

2019-01-11 09:00:00

2019-07-10 12:40:29

Linux虛擬地址空間物理地址空間

2010-10-16 11:43:45

WindowsDEPASLR

2024-01-08 08:42:43

2009-09-16 08:43:51

linux進(jìn)程線程

2014-08-01 15:38:37

Linux進(jìn)程管理

2010-01-05 10:00:48

Linux進(jìn)程間通信

2023-04-13 08:09:35

操作系統(tǒng)虛擬地址內(nèi)存

2010-05-13 09:45:26

Linux地址空間

2009-12-07 09:31:23

Linux系統(tǒng)調(diào)用表地址

2018-05-18 08:43:27

Linux內(nèi)存空間
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产精品99一区二区 | 国产精品视频一区二区三区四蜜臂 | 国产午夜精品久久久久 | 六月色婷 | 欧美一区二区三区视频在线观看 | 九九九色| 久久久久久a | 午夜视频大全 | 中文字幕精品一区二区三区精品 | 色视频网站免费 | 日韩精品 电影一区 亚洲 | 18av在线播放 | 久热国产精品视频 | 国产1区在线 | 欧美毛片免费观看 | 国产精品视频二区三区 | 99久9| 国产精品不卡一区 | 成人一区av偷拍 | 精品久久久久久亚洲精品 | 日本视频免费 | 亚洲高清在线免费观看 | av一区二区在线观看 | 欧美日韩专区 | 91视频入口 | 亚洲黄色av| 欧美亚洲一区二区三区 | 在线观看免费黄色片 | 日韩一区二区在线观看视频 | 久草网在线视频 | 日韩一二区 | 精品久久久久久久久久久久久久 | 国产亚洲网站 | 久久大陆 | 黄a大片 | av网站免费 | 国产一区二区三区四区hd | 国产999在线观看 | 欧美福利久久 | 午夜男人天堂 | 在线欧美亚洲 |