進程地址空間(linux)

linux下,進程的地址空間是由允許進程使用的全部線性地址組成。在32位系統中進程地址空間的大小一般爲4GB.
內核通過線性區來管理進程的內存地址,線性區通過鏈表和紅黑樹進行組織,方便查收、增加以及刪除等操作。
線性區大致分爲如下幾類:text段、data段、heap段、stack段、內存映射以及匿名段段等
下面以一個C程序爲例,展示各個線性區的內存地址:
debian:/home/bsh/process_as# cat main.c 


   /*
   * ch03-memaddr.c --- Show address of code, data and stack sections, as well as BSS and dynamic memory.
   
This program prints the locations of the two functions main() and afunc() (lines 22–23). It then shows how the stack grows downward, letting afunc() (lines 51–63) print the address of successive instantiations of its local variable stack_var. (stack_var is purposely declared auto, to emphasize that it's on the stack.) It then shows the location of memory allocated by alloca() (lines 28–32). Finally it prints the locations of data and BSS variables (lines 34–38), and then of memory allocated directly through sbrk() (lines 40–48). Refernce: http://www.phptr.com/articles/article.asp?p=173438&seqNum=2


   */


  #include <stdio.h>
  #include <malloc.h>     /* for definition of ptrdiff_t on GLIBC */
  #include <unistd.h>
  #include <alloca.h>     /* for demonstration only */


  extern void afunc(void);    /* a function for showing stack growth */


  int bss_var;            /* auto init to 0, should be in BSS */
  int data_var = 42;      /* init to nonzero, should be data */


  int
  main(int argc, char **argv) /* arguments aren't used */
  {
      char *p, *b, *nb;


      printf("Text Locations:\n");
      printf("\tAddress of main: %p\n", main);
      printf("\tAddress of afunc: %p\n", afunc);


      printf("Stack Locations:\n");
      afunc();


      p = (char *) alloca(32);
      if (p != NULL) {
          printf("\tStart of alloca()'ed array: %p\n", p);
          printf("\tEnd of alloca()'ed array: %p\n", p + 31);
      }


      printf("Data Locations:\n");
      printf("\tAddress of data_var: %p\n", & data_var);


      printf("BSS Locations:\n");
      printf("\tAddress of bss_var: %p\n", & bss_var);


      b = sbrk((ptrdiff_t) 32);   /* grow address space */
      nb = sbrk((ptrdiff_t) 0);
      printf("Heap Locations:\n");
      printf("\tInitial end of heap: %p\n", b);
      printf("\tNew end of heap: %p\n", nb);


      b = sbrk((ptrdiff_t) -16);  /* shrink it */
      nb = sbrk((ptrdiff_t) 0);
      printf("\tFinal end of heap: %p\n", nb);


      /* infinite loop */
      while (1) {}
  }


  void
  afunc(void)
  {
      static int level = 0;       /* recursion level */
      auto int stack_var;        /* automatic variable, on stack */


      if (++level == 3)           /* avoid infinite recursion */
          return;


      printf("\tStack level %d: address of stack_var: %p\n",
              level, & stack_var);
      afunc();                    /* recursive call */
  }
          源碼引自http://alumni.cs.ucr.edu/~saha/stuff/memaddr.html
上述程序的輸出(Linux debian 2.6.32-5-686 #1 SMP Wed Jan 12 04:01:41 UTC 2011 i686 GNU/Linux):
debian:/home/bsh/process_as# ./main &
[1] 6275
debian:/home/bsh/process_as# Text Locations:
        Address of main: 0x8048424
        Address of afunc: 0x8048588
Stack Locations:
        Stack level 1: address of stack_var: 0xbfa1ec9c
        Stack level 2: address of stack_var: 0xbfa1ec6c
        Start of alloca()'ed array: 0xbfa1ec90
        End of alloca()'ed array: 0xbfa1ecaf
Data Locations:
        Address of data_var: 0x8049910
BSS Locations:
        Address of bss_var: 0x8049920
Heap Locations:
        Initial end of heap: 0x8c70000
        New end of heap: 0x8c70020
        Final end of heap: 0x8c70010
程序的maps
debian:/home/bsh/process_as# cat /proc/6275/maps 
08048000-08049000 r-xp 00000000 08:01 1212791    /home/bsh/process_as/main
08049000-0804a000 rw-p 00000000 08:01 1212791    /home/bsh/process_as/main
08c70000-08c71000 rw-p 00000000 00:00 0          [heap]
b7774000-b7775000 rw-p 00000000 00:00 0 
b7775000-b78b5000 r-xp 00000000 08:01 102543     /lib/i686/cmov/libc-2.11.2.so
b78b5000-b78b7000 r--p 0013f000 08:01 102543     /lib/i686/cmov/libc-2.11.2.so
b78b7000-b78b8000 rw-p 00141000 08:01 102543     /lib/i686/cmov/libc-2.11.2.so
b78b8000-b78bb000 rw-p 00000000 00:00 0 
b78d3000-b78d6000 rw-p 00000000 00:00 0 
b78d6000-b78d7000 r-xp 00000000 00:00 0          [vdso]
b78d7000-b78f2000 r-xp 00000000 08:01 71216      /lib/ld-2.11.2.so
b78f2000-b78f3000 r--p 0001a000 08:01 71216      /lib/ld-2.11.2.so
b78f3000-b78f4000 rw-p 0001b000 08:01 71216      /lib/ld-2.11.2.so
bfa0c000-bfa21000 rw-p 00000000 00:00 0          [stack]
對此程序各線性區的分析:
線性區名稱                       起始地址                  線性區內容
text段                           08048000-08049000         main、afunc
data段                           08049000-0804a000         data_var、bss_var
heap段                           08c70000-08c71000         Initial(New、Final) end of heap
內存映射及匿名段                 b7774000-b78f4000
stack段                          bfa0c000-bfa21000         start(End) of alloca()'ed array    


注:0x08048000是在x86系統上linux加載程序的默認地址,在2.6.9版本內核後加入了靈活佈局,可以看到 內存映射及匿名段 緊接用戶態堆棧尾。新的區域往更低地址追加,即往堆的方向擴展。   
發佈了24 篇原創文章 · 獲贊 3 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章