我对 TLDP 中虚拟内存的解释完全困惑:
http://www.tldp.org/LDP/tlk/kernel/processes.html#tthFtNtAAB
他们说:
每个单独的进程都在自己的虚拟地址空间中运行,除非通过安全的内核管理机制,否则无法与另一个进程交互。
“自己的虚拟地址空间”对我来说是 32 位模式下自己的 4Gb RAM:0000:0000 - FFFF:FFFF。但他们并不是这个意思,对吧?如果两个进程指向虚拟地址1111:1111,那么它们意味着相同的物理地址,那么所有进程共享相同的4 Gb虚拟地址空间?
此外,我读过有关 Windows 的文章这里, 他们真的每个进程都有单独的虚拟地址空间,用户模式有单独的 2Gb RAM,内核模式共享 2Gb RAM,因此 2 个不同的进程都可以指向 1111:1111,映射到不同的物理内存。他们吗? :)
更新:我的问题的插图。哪张图片适合 Linux:
情况1:
案例2
答案1
Linux 和 Windows 在这里的工作方式几乎相同。每个进程都有自己的“虚拟”地址空间。这并不意味着内存实际上是物理可用的(显然大多数 32 位计算机从来没有足够的内存),这就是为什么它是虚拟的。
此外,那里使用的地址与物理地址不对应。因此 AAAA:0000 处的物理内存段可以对应于 9128:2af2,重点是你不必关心。应用程序所关心的只是感兴趣的内容位于其自己的内存段中的位置。是的,这也意味着两个应用程序可以在自己的内存视图中指向相同的地址并获得不同的东西。
除了进程的实际物理内存页面之外,还有很多有趣的东西可以映射到那里,例如属于设备的地址(例如视频卡)、动态链接库或进程之间共享的内存(这是“安全的内核管理机制”是什么意思)。
如果您想更深入地研究虚拟内存和进程地址空间布局,或者如果您无法轻松掌握一本,我可以向您推荐一本像《Tanenbaum》《操作系统》这样的教科书http://duartes.org/gustavo/blog/post/anatomy-of-a-program-in-memory也值得一读。
答案2
“自己的虚拟地址空间”实际上与你所说的相反:它意味着地址11111111指向一个不同的每个进程在物理内存中的位置。如果虚拟地址对应于不同进程中的相同物理地址,则进程将共享地址空间。事实上,一些地址空间是在多个进程之间共享的(例如, after fork
,几乎所有页面都在父进程和子进程之间共享)。这对应于您的“案例 2”图片。 Linux 和 Windows 在这方面没有什么不同。
fork
Linux 实际上可以在一些小型嵌入式设备上运行(以降级模式,其中不支持这种模式)内存管理单元,只有一个MPU(内存保护单元)。在此类设备上,没有虚拟地址空间(情况 2),但进程之间仍然存在分离,因为每个进程对内存页面都有自己的一组权限。