原创 Linux应用程序在内存中的地址布局

2015-3-2 17:03 1160 0 分类: MCU/ 嵌入式 文集: Linux应用程序开发学习
 在学习Linux应用程序开发中,经常会遇到以下概念:栈(Stack)、堆(heap)、BSS段(Block Started by Symbol,又名未初始化数据段)、数据段、代码段。而这些概念也是构成Linux应用程序的重要组成部分。
 内存布局
  当Linux应用程序在内存中运行时,以上组成部分又是怎样在内存中布局的呢?
  

  
lhtc3duk9prh4ddifac1no3g51_8d5d1353e9858b9d8f8b27776afd88961425286659.819.jpg

1、从低地址到高地址依次为:代码段、数据段、BSS段、堆、栈
2、堆向高内存地址增长
3、栈向低内存地址增长
4、所有的应用程序的代码段的起始地址都为0x0804 8000,此处的0x0804 8000为虚拟地址
 
一、接下来让我们通过程序验证查看程序各段地址。
编译附录中的源码  --->  运行  --->   查看进程PID(命令为:ps aux)  --->  再打开一个终端输入命令(cat /proc/2995(PID号)/maps
lhtc3duk9prh4ddifac1no3g51_d2dd9acdd5f235d0051cf992d9d1ca561425286830.8413.jpg
skitch.jpg
 
二、分析BSS段存放数据内容。通过readelf -S filename 来查看。
(zhaoxi.net).jpg
 
结论:  
          栈:局部变量(初始化的和未初始化的,但不包含局部静态变量)、局部只读变量(const)
          堆:动态分配的区域(如使用malloc函数申请的区域)
          BSS段:存储未初始化的全局变量和静态变量
          数据段:存储初始化的全局变量和静态变量
          代码段:代码、全局const常量、字符常量
附录源码:
#include
#include
int global_init = 1;//全局,初始化  数据段
int global_uninit;//全局,未初始化  数据段

static global_static_init = 1;//全局,静态,初始化  数据段
static global_static_uninit;//全局,静态,未初始化  数据段

const int global_a = 1; //全局,常量,初始化  代码段
const int global_b;//全局,常量,未初始化 数据段
int main( )
{
     int local_init = 1;//局部,初始化 栈
     int local_uninit;//局部,未初始化  栈

     static local_static_init = 1;//局部,静态,初始化  数据段
     static local_static_uninit;//局部,静态,未初始化  数据段

     const int local_a = 1;//局部,常量,初始化 数据段
     const int local_b;//局部,常量,未初始化 数据段
     int* p = (int*)malloc(10);// 动态申请内存 堆

     printf("global_init = %p \n",&global_init );
     printf("global_uninit = %p \n",&global_uninit );
     printf("global_static_init = %p \n",&global_static_init );
     printf("global_static_uninit = %p \n",&global_static_uninit );
     printf("global_a = %p \n",&global_a );
     printf("global_b = %p \n",&global_b );

     printf("local_init = %p \n",&local_init );
     printf("local_uninit = %p \n",&local_uninit );
     printf("local_static_init = %p \n",&local_static_init );
     printf("local_static_uninit = %p \n",&local_static_uninit );
     printf("local_a = %p \n",&local_a );
     printf("local_b = %p \n",&global_b );
     printf("malloc = %p\n",p );
     return 0;
}
广告

文章评论 0条评论)

登录后参与讨论
相关推荐阅读
潇洒哥 2015-07-08 16:01
位操作符的使用技巧
在C语言编程中,数据的位是可以操作的最小数据单位,理论上可以用“位运算”来完成所有的运算和操作。一般的位操作是用来控制硬件的,或者做数据变换使用,但是,灵活的位操作可以有效地提高程序运行的效...
潇洒哥 2015-04-04 17:39
finish shell分析之底层usart
rt_thread的finsh shell系统不愧是调试的一项利器,它可以除了完成一般shell的功能外,甚至还可以自定义命令。这个对功能单一的嵌入式系统来说是十分可贵的。在此我并不想对finsh...
潇洒哥 2015-04-01 21:29
__main() 和 main()
因为我们通常在BOOTLOADER中都已做好了比较细致的初始化工作,包括代码的搬运,所以我们最好别再调用库函数__main(),因为__main()作为ADS集成好的库函数,会对系统进行初始化设置...
潇洒哥 2015-03-26 22:54
RT-Thread学习之scons篇--解析rtconfig.py文件
rtconfig.py文件,主要用于指定编译器以及安装路径。除此之外,该文件中定义了大量的变量,这些变量包括编译选项,汇编选项,链接选项。   import os # toolchain...
潇洒哥 2015-03-26 22:53
RT-Thread学习之scons篇--SConsruct脚本文件解析
       scons的构建文件名称是统一的都称为SConstruct。其是scons所接受的编译脚本主文件。当然为了方便目录的组织,也允许在各个目录下面存放SConscript, 然后最上面S...
潇洒哥 2015-03-26 22:53
RT-Thread学习之scons篇--SConcript文件解析
SConscript文件是用来指定哪些文件会加入编译。先来分析下BSP主目录下的SConscript文件: import rtconfig Import('RTT_ROOT') fro...
广告
我要评论
0
0
广告
关闭 热点推荐上一条 /1 下一条