Linux Programming by Example:The Fundamentals(Notes One)

                                                 Chapter 3 User-Level Memory Managment

 

3.1  Linux/Unix 地址空间

众所周知,操作系统把一个可执行的程序载入内存中,这个可执行程序可称为一个进程。操作系统为程序访问命令行和环境变量做好准备,将程序开启运行。分配进程的内存可分为以下五个区域:

①代码段 (文本段-text segment)

可执行指令放在这个区域。如果可能,Linux/Unix会安排好相同程序的多个运行实体共享这些实例代码。任何内存只有一份相同程序的指令拷贝。可执行文件中包含文本段的部分叫文本结点(text section)。

②数据段 (data segment)

初始化为非零值的静态分配数据和全局数据存放在数据段中。运行相同程序的每个进程都有自己的数据段。可执行文件中包含数据段的部分是数据结点(data section)。

③BSS 段(Block Started by Symbol)

缺省初始化为零的全局数据和静态分配的数据存放在进程的BSS区域。每个运行相同程序的进程都有自己的BSS区域。当程序运行的时候,把BSS数据放到数据段。BSS数据存放在BSS节当中。

④堆 (Heap)

    用于分配动态内存 (由malloc()等一组函数得到)。当在堆上分配内存的时候,进程地址空间将增大。(可有ps命令查看)。一般情况下,堆是向上增长的。

⑤栈 (Stack)

    堆栈段(stack segment)用于分配本地变量(local invarible)的地方。本地变量是声明在函数体开始左大括号内的变量(或其它左大括号),不可以定义成static变量。

    大部分体系中,函数的参数也放在堆栈里,还有编译器产生的不可见的薄记信息,例如薄记信息中有存放函数返回值和返回地址的存储空间。正是在函数参数和返回值上使用了堆栈才使递归函数的编写变得方便了。当函数返回的时候,存储在堆栈里的函数变量消失了,堆栈里的空间又可以重新用于后面的函数调用。大部分体系中,堆栈是向下增长的。

 

当程序运行的时候,初始化数据、BSS和堆栈区域通常放在一个单独的连续区域:数据段。堆栈段和代码段与数据段是分隔开的。

下面为了证实地址空间的各个区域的确存在,给出如下测试程序:

-------------------------------------------------------------------CODE----------------------------------------------------------------------

/*

*        ch03-memaddr.c--------------显示代码段、数据段、堆栈段的地址,

*                                                          以及BSS段和动态内存的地址

*/

#include <stdio.h>

#include <malloc.h>

#include <unistd.h>

#include <alloca.h>

extern void afunc( void );

 

int bss_var;

int data_var=42;

int

main(int argc, char** argv)

{

     char *p, *b, *nb;

     printf("/tAddress of main :%p/n", main);

     printf("/taddress of afunc:%p/n", afunc);

     printf("Stack Loactions:/n);

     afunc( ) ;

     p=( char * ) alloca( 12 );

    if ( p !=NULL) {

             printf("/tStack of alloca( )'e array : %p/n", p );

             printf("/tEnd of alloca( )'e 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 );                                                   /* 扩大此程序的地址空间 */

   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 );                                               /* 缩小此程序的地址空间 */

   nb = sbrk ( ( ptrdiff_t ) 0 );                                                /* 得到缩小了的地址空间目前结束的地方 */

   printf ( "/t Final end of heap : %p/n, nb );

}

void

afunc( void )

{

       static int level = 0;

       auto int stack_var;

       if ( ++level == 3)

              return;

      printf ( " /tStack level %d : address of stack_var : %p/n", level,  & stack_var );

      afunc();

}

---------------------------------------------------CODE END-------------------------------------------------------------------------------

     在Linux系统下,或者在Windows 的 Cygwin 下用GCC编译并执行此程序得如下结果:

____________________________________________________________________________________

$gcc -o ch03-memaddr ch03-memaddr.c

$ ./ch03-memaddr

Text Locations:

               Address of main: 0x401050           

               Address of afun: 0x4011c4

Stack Locations:

              Stack level 1 : address of stack_var: 0x22eef4

              Stack level 2 : address of stack_var: 0x22eed4                      栈向下增长

              Stack of alloca()e array : 0x22ee0;

              End of alloca()e array : 0x22eeff                                                地址在栈上

Dara Locations:

             Address of data_var : 0x402000

BSS Locations:

             Address of bss_var : 0x404030                                                  BSS 段变量在Data段变量之上

Heap Locations :

            Initial end of heap : 0x4b1000                                                      Heap 紧接着在BSS段之上

            New end of heap : 0x4b1020                                                       并且 Heap 向上增长

            Final end of heap : 0x4b1010                                                      地址空间可以收缩____________________________________________________________________________________

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值