Linux進程地址空間

轉自:http://blog.chinaunix.net/uid-27119491-id-3325943.html

下圖是x86_64linux進程的默認內存佈局形式:

下面逐一分析以上各個地址段的含義。

 

text 代碼段

代碼段,從虛擬內存地址00400000開始,使用pmap $$可以查看到,這個地址是固定的:

  1. linux # pmap $$
  2. 27729: bash
  3. START          SIZE   RSS   PSS  DIRTY SWAP PERM MAPPING
  4. 00400000       552K  480K  260K     0K   0K r-xp /bin/bash
  5. 00689000         4K    4K    4K     4K   0K r--p /bin/bash
  6. 0068a000        20K   20K   20K    20K   0K rw-p /bin/bash
  7. 0068f000      1420K 1356K 1356K  1356K   0K rw-p [heap]
  8. 7f4f47b72000    64K    4K    4K     0K   0K r-xp /usr/lib64/gconv/libGB.so
  9. ……
  10. 7f4f48c33000     4K    4K    4K     4K   0K rw-p [anon]
  11. 7fff0f0f1000    84K   20K   20K    20K   0K rw-p [stack]
  12. 7fff0f1ff000     4K    4K    0K     0K   0K r-xp [vdso]
  13. ffffffffff600000 4K    0K    0K     0K   0K r-xp [vsyscall]
  14. Total:       18944K 3256K 2225K  1580K   0K
  15. 1652K writable-private, 17052K readonly-private, 240K shared, and 3256K referenced

00400000地址段用於存放程序的可執行文件,fork一個子進程,之後調用execve加載可執行文件,execve即將文件加載到該段地址中:

  1. linux # strace ls
  2. execve("/bin/ls", ["ls"], [/* 65 vars */]) = 0
  3. brk(0) =0x618000
  4. mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) = 0x7f0422e2a000
  5. ……


data 數據段

數據段用於存放已初始化全局變量。

 

bss

該段用於存放全局的、但未初始化的變量。bss段與data段的區別是,編譯時需爲data段分配空間,而bss段不用。數據存放於bss段,減小了可執行程序的文件大小。

 

heap

堆,c庫中的malloc調用就是從該段獲取內存空間。

 

memory map

mmap系統調用可將文件映射入進程memory map地址空間。使用pmap $$查看,[heap]下面部分就是mmap區域,對於以上"pmap $$"輸出:

  1. 7f4f47b72000  64K  4K  4K  0K  0K  r-xp        /usr/lib64/gconv/libGB.so

bash進程將/usr/lib64/gconv/libGB.so文件映射到以7f4f47b72000開頭的地址段。

使用ldd命令,我們可以看到進程依賴的庫文件,這些庫文件編譯過程中都要關聯到進程的虛擬地址空間:

  1. linux # ldd /bin/bash
  2.   linux-vdso.so.1 => (0x00007fffc73ff000)
  3.   libreadline.so.5 => /lib64/libreadline.so.5 (0x00007f7effe50000)
  4.   libdl.so.2 => /lib64/libdl.so.2 (0x00007f7effc4c000)
  5.   libc.so.6 => /lib64/libc.so.6 (0x00007f7eff8ee000)
  6.   libncurses.so.5 => /lib64/libncurses.so.5 (0x00007f7eff6a6000)
  7.   /lib64/ld-linux-x86-64.so.2 (0x00007f7f00092000)

 

stack

存放局部變量,從高地址向低地址生長。

 

內核代碼中,mm_struct結構用於描述一個進程的地址空間。

 

vm_area_struct用於描述一段地址,linux提供了/proc/PID/maps接口,我們可以通過該接口查詢某進程的虛擬地址段:

  1. linux # cat /proc/$$/maps
  2. 00400000 - 00486000   r-xp 00000000 08:02 18104 /bin/bash
  3. 00586000 - 00586000   rw-p 00086000 08:02 18104 /bin/bash
  4. 0058b000 - 0073b000   rw-p 0058b000 00:00     0 [heap]
  5. 2b7c1ff67000 - 2b7c1ff82000 r-xp 00000000 08:02 12969 /lib64/ld-2.4.so
  6. ……
  7. 7fff8ab2d000 - 7fff8ab43000 rw-p 7fff8ab2d000 00:00 0 [stack]
  8. ffffffffff600000 - ffffffffffe00000 ---p 00000000 00:00 0 [vdso]

c庫中的malloc底層通過mmapbrk實現內存申請。mmap可用於關聯文件到進程的虛擬地址空間,也可用於申請匿名地址空間。

  1. void *mmap( void *addr, size_t length, int prot, int flags, int fd, off_t offset);

若指明fd就是關聯文件到虛擬地址空間,沒有指明就是申請匿名地址空間。

 

brk調用只是增加heap這一段虛擬內存空間,sbrk用於實際的內存申請。


Reference: Chapter 15 - The Process Address Space, Linux kernel development.3rd.Edition


發佈了68 篇原創文章 · 獲贊 45 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章