购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2.6 ELF文件的主要段

可使用命令readelf-segments executableFile查看文件的段信息。ELF文件的主要段有:

●代码段(text):用于存放函数命令。

●数据段(data):用于存放已经初始化的全局变量和静态变量。

●只读数据段(rodata):用于存放只读常量或const关键字标识的全局变量。

●bss段(block started by the symbol):用于存放未初始化的全局变量和静态变量,这些变量由于未初始化,所以没有必要在ELF文件中为其分配空间,bss段的长度总为0。

●调试信息段(debug):用于存放调试信息。

●行号表(line):用于存放编译器代码行号和命令的对应关系。

●字符串表(strtab):用于存储ELF文件中的各种字符串。

●符号表(symtab):用于ELF文件中各种的符号。

ELF文件的运行是指将硬盘上存储的文件调入并装载进内存,程序中各种段就会被装载在内存地址空间中,形成自己的内存空间布局。其中,ELF文件的PT_LOAD段是可加载的段,分别由p_filesz和p_memsz指定文件的大小和内存的大小。

在内存模型中,进程的内存空间主要由6部分组成,如图2.13所示。

图2.13 进程内存空间的组成

其中,存储在.rodata中的数据是只读的,存储的是常数(带const修饰符)和字符串。局部变量和函数参数分别在栈中分配(栈和堆分别在内存中分配,在ELF文件中不存在对应的部分)。

查看各个段的装载内存布局命令如下:

2.2.6.1 全局变量和静态变量的存储

全局变量和静态变量存储在.data和.bss中。其中,未被初始化的存储在.bss中,已被初始化(不为0)的存储在.data中。这些变量存储的区域是静态存储区。

我们将Listing 2.14作为基准源码,看看全局变量和静态变量的存储。

Listing 2.14 测试.text、.bss和.data的基准源码cMemoryLayout-simple.c

全局数量和静态变量的存储如下:

Listing 2.15 在基准源码上增加未被初始化的全局变量的源码cMemoryLayout-simplev2.c

未被初始化的全局变量的存储如下:

Listing 2.16 在基准源码上增加未被初始化的全局变量和静态变量的源码cMemoryLayout-simplev3.c

未被初始化的全局变量和静态变量的存储如下:

Listing 2.17 在基准源码上增加未被初始化的全局变量和初始化静态变量的源码cMemoryLayout-simplev4.c

未被初始化的全局变量和初始化静态变量的存储如下:

Listing 2.18 在基准源码上增加已被初始化的全局变量和静态变量的源码cMemoryLayout-simplev5.c

已被初始化的全局变量的存储如下:

Listing 2.19 在基准源码上增加const全局变量的源码cMemoryLayout-simplev6.c

const全局变量的存储如下:

Listing 2.20 在基准源码上增加const全局变量和字符串常量的源码cMemoryLayout-simplev7.c

const全局变量和字符串常量的存储如下:

2.2.6.2 局部变量在堆和栈中的存储

局部变量和函数参数是在函数调用过程中动态申请和释放的,存储在栈中。栈从高地址往低地址增长。程序的运行可以没有堆(Heap),但必须得有栈(Stack)。当调用函数时就会在栈上新建一个栈帧,当函数调用结束时,栈帧就会从栈上移除。

用户通过malloc/realloc/calloc申请的空间在堆中,通过free()函数释放堆空间。栈和堆都是动态存储区。

Listing 2.21 进程在堆和栈空间布局的测试源码stackHeapTest.c

Listing 2.21对应的例程在栈和堆中的布局如图2.14所示。

图2.14 Listing 2.21对应的进程在堆和栈中的布局 wDdmtflBVVHn6zALVNR8NRlLiO/d1qK286fiVc1vYy6XY0+leh3rKalNby1r27Fy

点击中间区域
呼出菜单
上一章
目录
下一章
×