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版本内核后加入了灵活布局,可以看到 内存映射及匿名段 紧接用户态堆栈尾。新的区域往更低地址追加,即往堆的方向扩展。
内核通过线性区来管理进程的内存地址,线性区通过链表和红黑树进行组织,方便查收、增加以及删除等操作。
线性区大致分为如下几类: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版本内核后加入了灵活布局,可以看到 内存映射及匿名段 紧接用户态堆栈尾。新的区域往更低地址追加,即往堆的方向扩展。