为了减少页的对齐产生的内存浪费,对于相同权限的段,将他们合并在一起当做一个段来进行映射,ELF 可执行文件将这称为 Segment ,在映射之后 VMA 就减少了
使用 readelf -l
查看 elf 的 segment
从装载的角度看,只有 LOAD 类型的 segment 是需要被映射的,其他的诸如 NOTE、TLS 都是在装载的时候起辅助作用的
Segment 和 Section 是从不同的角度来划分同一个 ELF 文件,称为不同的视图(View),从 Section 角度来看 ELF 文件就是 链接视图(Linking View),从 Segment 角度来看就是 执行视图(Execution View)
在 ELF 文件结构 中有一个专门的数据结构叫 程序头表(Program Header Table)来保存 Segment 的信息。和 readelf -l
打印的信息一一对应
此时 BSS 段已经合并到其他数据类型的段里面去了
查看 /proc/<pid>/maps
可以看到虚拟空间分布,其中 stack 和 heap 和 vdso 没有主设备号和次设备号,也没有映像文件的节点号,这种 VMA 称为 匿名虚拟内存区域
为了解决不同权限分页之间的空间浪费,采取直接最大程度直接从可执行文件到物理内存分页(先不管权限的事),再映射次到虚拟内存上,接壤的分页映射多次,让各个段接壤部分共享同一个物理界面,通过增加虚拟内存的占用,减少了物理内存的浪费
对于一般的 align 远小于 page 的情况下,虚拟内存地址 p_vaddr
和偏移地址 p_offset
关于 align 同余