页是虚拟内存的最小可映射单元。如果您不熟悉基础知识,请参阅the wikipedia article on virtual memory。在普通系统上,页面大小为 4096 字节,即 0x1000(十六进制)。
“文本页面”包含可执行代码; “数据页”包含数据。这些必须映射到固定地址,以便代码中的偏移量正确。在共享库或与位置无关的可执行文件中,不再指定确切的虚拟地址,而是指定它们的相对位置。在这个例子中,第 0 个文本页从 0x8048000 到 0x8048fff,它在文本段开始之前(在 0x8048100)。第一个文本页从 0x8049000 到 0x8049fff。最后一个文本页从 0x8073000 到 0x8073fff,超出了文本段的末尾(在 0x8073eff)。
第一个数据页位于 0x8074000,但数据段直到 0x8074f00 才开始。此页面由文件的 same 部分作为最后一个文本页面的支持,但必须单独映射,因为它具有不同的权限(PROT_EXEC|PROT_READ 与 PROT_READ)。这就是“数据开头的副本”/“文本结尾的副本”的含义。
如果有两个以上的段,则加载完全相同。 “文本”和“数据”是完全任意的,重要的是为每个段指定的标志和地址。您可以通过readelf 或objdump 查看此信息。
请注意,在现实世界中,文本和数据段之间通常有一个未映射的空间(“洞”),但不一定在只读数据和读写数据之间或初始化与未初始化数据之间。
例如,运行 cat /proc/self/maps 给我:
ben@joyplim ~ % cat /proc/self/maps
00400000-0040c000 r-xp 00000000 fe:01 36176026 /bin/cat
0060b000-0060c000 r--p 0000b000 fe:01 36176026 /bin/cat
0060c000-0060d000 rw-p 0000c000 fe:01 36176026 /bin/cat
<plus the heap, stack, library, and special kernel stuff>