指针是指向物理内存还是虚拟内存?

9

我最近了解到计算机程序实际上并没有使用物理内存地址。相反,我理解操作系统会将物理内存“隐藏”起来供应用程序使用。

这里有一个问题: 指针返回的是物理内存地址还是虚拟内存地址?

如果我执行以下代码,我会得到一个十六进制的地址形式。这只是由操作系统随机分配的数字吗?我还发现数组中元素的地址是连续分配的。这是否意味着数组实际上在RAM中是按“行”排列的,还是可能在稀疏区域中分配它们,而操作系统仅是模拟程序员?

int num = 3;
int arr[3];

printf("address of num: 0x%0x \n", &num);
printf("&arr[0]: 0x%0x \n", &arr[0]);
printf("&arr[1]: 0x%0x \n", &arr[1]);
printf("&arr[2]: 0x%0x \n", &arr[2]);

1
实际上,这取决于情况。如果您使用的操作系统没有虚拟内存,或者您正在编写(部分)内核代码,则它将指向物理地址。如果您正在编写一个将在操作系统顶部运行的应用程序,也就是在用户模式下运行,并且操作系统使用虚拟内存,则它将指向虚拟地址。请参阅https://dev59.com/ul8d5IYBdhLWcg3wpzhf 了解更多信息。 - Sreeram TP
2
可能是Does a C pointer refer to the physical or virtual address的重复问题。 - Sreeram TP
1
程序使用指针,因此它必须具有程序所看到的地址。如果系统为程序创建了虚拟地址空间,则程序使用虚拟地址。 - Eric Postpischil
2个回答

13
在所有现代操作系统(Windows、Linux、BSD等)中,用户空间应用程序中的所有地址都是虚拟地址。唯一的例外是某些RTOS或其他定制的裸机应用程序。
虚拟地址不一定是随机的,但从硬件的角度来看它们是任意的。内核通常会决定为给定的映射请求分配虚拟地址空间,有时会考虑用户空间的请求。当使用ASLR(现在很常见)等功能时,地址是故意随机化的。

这是否意味着数组实际上是在 RAM 中以'线性'形式存在的,或者它们可以被分配在稀疏区域中,操作系统只是伪造程序员?

两者皆可。操作系统创建物理到虚拟内存页的映射,而不是单个地址。页面大小因架构而异,但通常为4 KiB。
因此,如果您有一个1 KiB的数组(其起始地址至少为1 KiB对齐),它将是物理连续的。但如果有一个16 KiB的数组,则可能分散在4个彼此不相邻的页面中。

你确定1KiB数组是连续的吗?它可能会从一页开始,然后延续到下一页吗? - klutt
1
@Broman "一个1 KiB的数组(其起始地址至少为1 KiB对齐)" -- 假设页面大小为4 KiB,如果1 KiB块是1 KiB对齐的,则它将恰好适合该页面上的四个“插槽”中的一个。 - Jonathon Reinhart
非常感谢!它真的帮了我很多 :) - 김도윤

2

这取决于操作系统。但大多数情况下,它们是逻辑地址。

操作系统有虚拟内存、分页等机制来进行地址转换。通常这样做是为了确保程序不允许覆盖内存的某些部分。

如果你在没有操作系统处理虚拟地址的裸机内核上运行它,那么它将是物理地址。如果它作为应用程序在操作系统之上运行,你会得到虚拟地址。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接