我正在读Operating Systems: Three Easy Pieces。要了解程序的虚拟地址空间的外观,我运行以下代码。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
printf("location of code : %p\n", (void *) main);
printf("location of heap : %p\n", (void *) malloc(1));
int x = 3;
printf("location of stack : %p\n", (void *) &x);
return x;
}
其输出是:
location of code : 0x564eac1266fa
location of heap : 0x564ead8e5670
location of stack : 0x7fffd0e77e54
为什么代码段的位置是0x564eac1266fa
?在使用之前,这么大的(虚拟)空间是什么?为什么不从0x0
或附近开始
然后,为什么程序的虚拟地址这么大?(从堆栈位置开始,它的宽度为48位)是什么呢?
答案 0 :(得分:2)
可能的虚拟地址空间组织由您使用的硬件(特别是它支持的MMU)定义。然后,操作系统可以使用可以强制使用硬件的任何组织,但是通常,它仅直接使用(可能带有某些子集),因为这样最有效。
x86_64体系结构定义了一个48位虚拟地址空间 1 ,大多数操作系统保留一半的空间供系统使用,因此用户程序看到的是47位地址空间。在该地址空间内,大多数操作系统将随机化用于任何给定程序的地址,以使利用程序中的错误变得更加困难。
1 严格来说,该体系结构定义了一个64位虚拟地址空间,但是保留了所有不具有前17位全0或全1的地址。
答案 1 :(得分:0)
您正在用这里尝试做的事树错了。一个进程具有多个堆栈,可能具有多个堆,并且main可能不是代码的开始。将地址空间视为代码段,堆栈段,堆段……就像可怕的操作系统书籍一样,只会让您感到困惑。
由于逻辑寻址,映射到地址空间的内存不必是连续的。
为什么代码段的位置是0x564eac1266fa?在使用之前,这么大的(虚拟)空间是什么?为什么不从0x0或附近开始?
您的过程中的代码开始应为0x564eac1266f8。您拥有高地址这一事实并不意味着低位地址已被映射到进程地址空间中。
然后,为什么程序的虚拟地址这么大?(从堆栈位置开始,它的宽度为48位)。
堆栈通常从高处开始,然后从低处开始。