进程虚拟空间分布

ELF文件链接视图和执行视图

当我们站在操作系统装载可执行文件的角度看问题时,可以发现它实际并不关系可执行文件的实际内容,操作系统只关心一些跟装载有关的问题,主要是段的权限。ELF文件中,段只有几种组合,基本是以下三种:

以代码段为代表的权限为可读可执行的段。
以数据段和BSS段为代表的权限为可读可写的段
以只读数据段为代表的权限为只读的段

我们知道,因为页对齐的原因,当段的数量增多是,不可避免的就会产生空间浪费的问题。因此,对于相同权限的段,我们把他们合并到一起当作一个段进行映射
在ELF文件中,引入了一个概念叫“segment”,一个segment包含一个或多个属性类似的section(段)
“segment”的概念实际上是从装载的角度重新划分了ELF的各个段。在将目标文件链接成可执行文件的时候,链接器会尽量把相同的权限属性的段分配在同一空间。
所以总的来说,segmentsection是从不同的角度来看ELF文件,这就是ELF的不同视图

section是链接视图
segment是执行视图

堆和栈

在操作系统中,虚拟地址空间除了被用来映射可执行文件中的各个segment以外,它还可以有其他的作用。操作系统通过使用虚拟地址空间来对进程的地址空间进行管理。

操作系统通过给进程空间划分出一个个VMA来管理进程的虚拟空间。基本原则是将相同权限属性的、有相同映像文件的映射成一个VMA。一个进程基本上可以分为如下几种VMA区域。

代码VMA,权限只读、可执行;有映像文件
数据VMA,权限可读写,可执行;有映像文件
堆VMA,权限可读写、可执行;无映像文件
栈VMA,权限可读写,不可执行;无映像文件
注:可执行文件在装载时实际上是被映射的虚拟空间,所以可执行文件很多时候被叫做映像文件。

段地址对齐

概括一下:

section按属性相同合并成segment,segment通过两个相邻段逻辑上的合并,可以在相邻处合并成一个页表,共同借阅内存空间。


在这种情况下,内存空间得到了充分的利用,我们可以看到,本来要用到5个物理页面,也就是20 480字节的内存,现在只有3个页面,即12 288字节。这种映射方式下,对于一个物理页面来说,它可能同时包含了两个段的数据,甚至可能是多于两个段,比如文件头、代码段、数据段和BSS段的长度加起来都没超过4 096字节,那么一个物理页面可能包含文件头、代码段、数据段和BSS段。

参考文献

[1] 俞甲子 石凡 潘爱明.程序员的自我修养.电子工业出版社,2009.4.