程序构成
在学习Linux应用程序开发时,经常会遇到 如下概念
代码段、
数据段、
BSS段 (Block Started by Symbol,又名:未初 始化数据段) 、
堆(heap)栈(stack)。
而这些部分也是构成Linux应用程序的重要组 成部分。
内存布局
无论哪一个应用程序它的代码段起始地址一定是0x8048000,这里的地址虚拟地址,映射到不同的物理地址中去。
各段内容
通过命令ps -aux | grep app 可以查找app的pid
该进程在系统内存中的布局 (maps文件分析)
最上面 /lib 为库在内存中所在的位置
代码段: 只读 可执行 (r x) 起始地址: 8048000-8049000
数据段: 可写(w) 紧贴着代码段下面的 8049000-804a0000
堆: heap (r w)
栈: stack
#include <stdio.h> int global_init_a = 1; //全局初始化的变量 int global_uinit_a; //全局未初始化的变量 static int static_global_init_a = 1; //全局静态初始化变量 static int static_global_uinit_a; //全局静态未初始化变量 const int const_global_a = 1; //全局常量 int global_init_b = 1; //全局初始化的变量 int global_uinit_b; //全局未初始化的变量 static int static_global_init_b = 1; //全局静态初始化变量 static int static_global_uinit_b; //全局静态未初始化变量 const int const_global_b = 1; //全局常量 void main() { int local_init_a = 1; //局部初始化变量 int local_uinit_a; //局部未初始化变量 static int static_local_init_a = 1; //局部静态初始化变量 static int static_local_uinit_a; //局部静态未初始化变量 const int const_local_a = 1; //局部常量 int local_init_b = 1; //局部初始化变量 int local_uinit_b; //局部未初始化变量 static int static_local_init_b = 1; //局部静态初始化变量 static int static_local_uinit_b; //局部静态未初始化变量 const int const_local_b = 1; //局部常量 int *malloc_p_a; malloc_p_a = malloc(sizeof(int)); //通过malloc分配得到的局部 printf("&global_init_a=%p,global_init_a=%d\n",&global_init_a,global_init_a); printf("&global_uinit_a=%p,global_uinit_a=%d\n",&global_uinit_a,global_uinit_a); printf("&static_global_init_a=%p,static_global_init_a=%d\n",&static_global_init_a,static_global_init_a); printf("&static_global_uinit_a%p,static_global_uinit_a=%d\n",&static_global_uinit_a,static_global_uinit_a); printf("&const_global_a=%p,const_global_a=%d\n",&const_global_a,const_global_a); printf("&global_init_b=%p,global_init_b=%d\n",&global_init_b,global_init_b); printf("&global_uinit_b=%p,global_uinit_b=%d\n",&global_uinit_b,global_uinit_b); printf("&static_global_init_b=%p,static_global_init_b=%d\n",&static_global_init_b,static_global_init_b); printf("&static_global_uinit_b%p,static_global_uinit_b=%d\n",&static_global_uinit_b,static_global_uinit_b); printf("&const_global_b=%p,const_global_b=%d\n",&const_global_b,const_global_b); printf("&local_init_a=%p,local_init_a=%d\n",&local_init_a,local_init_a); printf("&local_uinit_a=%p,local_uinit_a=%d\n",&local_uinit_a,local_uinit_a); printf("&static_local_init_a=%p,static_local_init_a=%d\n",&static_local_init_a,static_local_init_a); printf("&static_local_uinit_a%p,static_local_uinit_a=%d\n",&static_local_uinit_a,static_local_uinit_a); printf("&const_local_a=%p,const_local_a=%d\n",&const_local_a,const_local_a); printf("&local_init_b=%p,local_init_b=%d\n",&local_init_b,local_init_b); printf("&local_uinit_b=%p,local_uinit_b=%d\n",&local_uinit_b,local_uinit_b); printf("&static_local_init_b=%p,static_local_init_b=%d\n",&static_local_init_b,static_local_init_b); printf("&static_local_uinit_b%p,static_local_uinit_b=%d\n",&static_local_uinit_b,static_local_uinit_b); printf("&const_local_b=%p,const_local_b=%d\n",&const_local_b,const_local_b); printf("malloc_p_a=%p,*malloc_p_a=%d\n",malloc_p_a,*malloc_p_a); while(1); }
结果分析:
全局初始化变量位于数据段
全局未初始化变量位于数据段
全局静态初始化变量位于数据段
全局静态未初始化变量位于数据段
全局常量位于代码段
局部初始化变量位于栈
局部未初始化变量位于栈
局部静态初始化变量位于数据段
局部静态未初始化变量位于数据段
局部常量位于栈
通过malloc分配的指针位于堆
数据存放
1.代码段: 代码,全局常量(const)、字符串常量
2.数据段: 全局变量(初始化以及未初始化的)、静态变量(全局的和局部的、初始化的以及未初始化的)
3.堆: 动态分配的区域
4.栈: 局部变量(初始化以及未初始化的,但不包含静 态变量)、局部只读变量(const)
BSS段
其实,BSS段是数据段的一个子集。 使用readelf工具查看
用file查看可执行程序的属性
linux下用gcc编译出来的程序是ELF格式的32位可执行程序 利用readelf可以提取出可程序程序的信息
通过read -S 程序名来分析BSS段(readelf -S /home/app)
全局未初始化的变量属于BSS段
全局未初始化的静态变量属于BSS段
通过分析可知,全局未初始化变量和全局静态未初始化变量都属于数据段里的BSS段。