虚拟地址空间

Viv*_*vek 6 linux memory-management process virtual-memory virtual-address-space

我已经开始了解虚拟地址空间(VAS),我有几个问题:

  1. 根据架构(32 位和 64 位),为每个进程创建多少 VAS?
  2. 每个进程的VAS都是在硬盘上创建的吗?如果是这样,如果空间不足怎么办?
  3. VAS 和虚拟内存 (VM) 有什么区别?

Ral*_*phS 8

虚拟地址与物理地址

在程序执行期间,变量(整数、数组、字符串等)存储在计算机主内存 ( RAM ) 中的某个位置。某些编程语言(如 C 或 C++)允许您获取存储给定变量的内存地址(使用运算符&),并操作该地址(添加、减去、打印等)。

下面是一个打印变量内存地址的 C 程序:

#include <stdio.h>

int main(void) {
    int variable = 1234;
    void *address = &variable;
    printf("Memory address of variable: %p\n", address);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

Memory address of variable: 0x7ffc9e9662a4
Run Code Online (Sandbox Code Playgroud)

现在,如果您在典型的台式计算机上使用典型的操作系统(如 GNU/Linux 或 Windows)编译并执行该程序,则该程序打印的内存地址并不是数据实际所在的硬件1234地址在存储芯片中。这可能令人惊讶,但程序使用的地址和硬件地址之间存在一定程度的间接性。

64 位计算机上的虚拟地址空间

在 64 位计算机上,程序操作的内存地址是 0 到 18446744073709551615(含)之间的整数。这样的地址称为虚拟内存地址。这些地址的范围称为进程的虚拟地址空间。您可以要求操作系统将一系列虚拟内存地址映射到计算机的物理内存,这样当您尝试在这些地址读取或写入字节时,您的程序就不会因访问未映射的虚拟内存地址而崩溃。

通常,在 x86-64 计算机上,只有 2 48 个虚拟内存地址可以成功映射到物理内存,因为 256 TiB 的可用虚拟地址空间被认为是足够的。将来,如果有需要,处理器制造商可能会提高或取消此限制。

32位计算机上的虚拟地址空间

在32位计算机上,有2个32个虚拟内存地址。在这些计算机上,程序操作的内存地址是 0 到 4294967295 之间的整数(包含 0 和 4294967295)。

在 x86 32 位计算机上,可映射到物理内存地址的虚拟内存地址范围通常没有限制。

映射虚拟内存地址范围

在 GNU/Linux 上,您可以通过调用函数 来请求映射mmap()。在 Windows 上,您可以通过调用函数来请求映射VirtualAlloc()。这些函数将映射的大小作为参数,并返回现在由实际物理内存支持的第一个虚拟地址。如果物理内存已被其他进程完全使用,这些函数可能无法创建新映射。同样,如果您尝试访问(读取或写入)位于mmap()或映射的区域之外的虚拟内存地址的内容VirtualAlloc(),操作系统将终止您的程序(通过发送分段错误信号)。

在 GNU/Linux 上,进程只需读取文件即可检查在其虚拟地址空间中创建的映射/proc/self/maps。通过阅读命令的输出,您可以学到很多东西cat /proc/self/maps

硬盘驱动器

在典型的计算机上,主存储器是半导体存储器硬盘驱动器只是辅助存储设备。

在典型的操作系统上,一系列虚拟内存地址只能映射到主内存(通常是半导体存储设备)。如果不使用主存储器作为中介,这样的范围不能直接映射到辅助存储设备(通常是硬盘驱动器)。


Him*_*war -2

    \n
  1. 虚拟地址空间 - 维基百科
  2. \n
\n
\n

当在 32 位操作系统上执行新应用程序时,该进程具有 4 GiB VAS:该空间中的每个内存地址(从 0 到 2 32 \xe2\x88\x92 1)都可以有一个字节,如下所示一个值。最初,它们都没有价值。

\n
\n

对于 n 位操作系统,这些 n 地址线允许地址空间最多 2 n个地址,即 0 到 2 n - 1。这对于 64 位操作系统来说意味着 16 EiB。(尽管在实际实现中,使用的空间较少,因为不需要这么多空间。)

\n
\n
    \n
  1. CPU 缓存 - 维基百科
  2. \n
\n
\n

大多数通用 CPU 都实现某种形式的虚拟内存。总而言之,机器上运行的每个程序都看到自己的简化地址空间,其中仅包含该程序的代码和数据,或者所有程序都在公共虚拟地址空间中运行。程序通过计算、比较、读取和写入其虚拟地址空间的地址来执行,而不是物理地址空间的地址,使得程序更简单,从而更容易编写。

\n
\n

例如,在C++中,程序内存分为栈、堆、数据、代码。我不确定类比是否正确(可能是),但如果您意识到的话,它在某种程度上提供了一种见解。

\n
\n
    \n
  1. 虚拟内存 - 维基百科
  2. \n
\n
\n

在计算中,虚拟内存是一种内存管理技术,它提供“给定机器上实际可用的存储资源的理想化抽象” 3,这“给用户带来了非常大(主)内存的错觉”。 [4]

\n
\n
\n

计算机的操作系统使用硬件和软件的组合,将程序使用的内存地址(称为虚拟地址)映射到计算机内存中的物理地址。从进程或任务的角度来看,主存储表现为连续的地址空间或连续段的集合。操作系统管理虚拟地址空间以及实内存到虚拟内存的分配。

\n
\n
\n

CPU 中的地址转换硬件通常称为内存管理单元 (MMU),可自动将虚拟地址转换为物理地址。操作系统内的软件可以扩展这些功能以提供可以超过实际内存容量的虚拟地址空间,从而引用比计算机中物理存在的内存更多的内存。

\n
\n

如果您了解计算机体系结构(我确信您从问题中了解了这一点),那么现在就已经澄清了。\n不过,对于一般人来说,我还是给出了一些解释。

\n
    \n
  • 假设 C++ 中的地址为指针。如果您不懂 C++,最接近的类比是任何语言中的数组/列表索引。现在地址指向内存位置,就像指针指向变量一样。实际数据存储在变量中。要使用指针/索引获取变量数据,您需要提供要从中提取数据的地址位置。现在在物理内存中,不会有变量之类的东西了。有内存及其访问它的位置地址。
  • \n
  • 真正的内存是物理内存,也就是硬盘。它是通过物理地址访问的,每个字节的物理地址都是唯一的。
  • \n
  • 直接用物理地址访问物理内存会很麻烦。因此,操作系统将地址简化为虚拟地址。这些地址可能是唯一的,也可能不是唯一的(请记住,这些地址不是物理地址)。因此,多个虚拟地址可以指向同一位置。
  • \n
  • 虚拟内存实际上并不存在,它只是使用虚拟地址简化的物理内存概念,为用户提供一个虚幻的空间,即下一个内存位置存储在下一个地址(准确地说是虚拟地址)。
  • \n
  • 由于可以使用MMU将多个虚拟地址映射到相同的物理地址,从而指向相同的物理内存位置,因此可以使虚拟内存大小(虚拟地)超过物理内存大小。但实际上,内存大小仍然与物理大小相同。
  • \n
\n

因此,为了访问内存数据,虚拟地址由用户/程序指定给操作系统,由内存管理单元(mmu)转换为物理地址,然后应用于计算机体系结构的地址线(电子发现!!),这会在相应的物理位置产生数据。这个概念称为虚拟内存。

\n

-希曼舒

\n