我的答案对于运行在现代 Linux 系统上的 Intel CPU 来说是正确的,而且我说的是用户级进程,而不是内核代码。尽管如此,我认为它会给你一些足够的洞察力来思考其他可能性
地址类型
关于问题3:
我遇到过虚拟和逻辑的讨论
地址/地址空间是相同的。这是真的吗?
据我所知,它们是相同的,至少在英特尔处理器上运行的现代操作系统中是这样。
在解释更多内容之前,让我尝试定义两个概念:
-
实际地址:RAM 芯片中某物物理位置的地址。
-
逻辑/虚拟地址:您的程序用来访问其内容的地址。它通常稍后由硬件芯片转换为物理地址(大多数情况下,甚至 CPU 都没有真正意识到这种转换)。
虚拟/逻辑地址
虚拟地址是一个虚拟地址,操作系统以及称为 MMU(内存管理单元)的硬件电路欺骗您的程序,它是在系统中单独运行的,它拥有整个地址空间(拥有 32 位系统意味着您的程序会认为它有 4 GB RAM;粗略地说)。
显然,如果您同时运行多个程序(您总是这样做,GUI、Init 进程、Shell、时钟应用程序、日历等),则这将不起作用。
将会发生的情况是,操作系统会将大部分程序内存放在硬盘中,它使用最多的部分将出现在 RAM 中,但是,嘿,这并不意味着它们将拥有您和您的程序的地址知道。
Example:您的进程可能有一个名为 (counter) 的变量,该变量被赋予虚拟地址 0xff(可以想象......),另一个名为 (oftenNotUsed) 的变量被赋予虚拟地址 (0xaa)。
如果您在所有链接发生后读取编译代码的汇编,您将使用这些地址访问它们,但是(oftenNotUsed)变量不会真正存在于 RAM 中的 0xaa 处,它将位于硬盘中因为该进程没有使用它。
此外,变量(计数器)可能不会物理上位于(0xff),它将位于 RAM 中的其他位置,当您的 CPU 尝试获取 0xff 中的内容时,MMU 和操作系统的一部分将进行映射从 RAM 中真正可用的位置获取该变量,CPU 甚至不会注意到它不在 0xff 中。
现在,如果您的程序要求 (oftenNotUsed) 变量,会发生什么? MMU+OS会注意到这个“未命中”,并将其从硬盘中为CPU获取到RAM中,然后将其交给CPU,就好像它位于地址(0xaa)中一样;此获取意味着 RAM 中存在的一些数据将被发送回硬盘。
现在想象一下它为系统中的每个进程运行。每个进程都认为自己有 4GB RAM,实际上没有人拥有,但一切正常,因为每个人的程序的某些部分在 RAM 中物理可用,但大部分程序驻留在硬盘中。不要将HD中的这部分程序存储器与您可以通过文件操作访问的程序数据混淆。
Summary
虚拟地址:您在程序中使用的地址,即您的 CPU 用于获取数据的地址,不是真实的,而是通过 MMU 转换为某个物理地址;每个人都有一个,其大小取决于您的系统(运行 32 位的 Linux 有 4GB 地址空间)
实际地址:如果您在操作系统之上运行,您将永远无法到达该地址。这是您的数据(无论其虚拟地址如何)驻留在 RAM 中的位置。如果您的数据来回发送到硬盘以便为其他进程提供更多空间,这种情况将会改变。
我上面提到的所有内容,虽然是整个概念的简化版本,但都是所谓的计算机系统的内存管理部分。
该系统的后果
- 进程无法访问彼此的内存,每个进程都有自己单独的虚拟地址,并且每个进程都会对不同区域进行不同的转换,即使有时您可能会发现两个进程尝试访问相同的虚拟地址。
- 该系统作为缓存系统运行良好,您通常不会使用可用的整个 4GB,那么为什么要浪费它呢?让其他人分享并让他们也使用它;当您的进程需要更多数据时,操作系统将从硬盘中获取您的数据并替换其他进程的数据,当然这是有代价的。