【问题标题】:Can malloc return same address in two different processes?malloc 可以在两个不同的进程中返回相同的地址吗?
【发布时间】:2012-07-04 22:36:04
【问题描述】:

假设我在 Linux 上有两个进程 a 和 b。在这两个过程中我都使用malloc() 来分配内存,

malloc() 是否有可能在两个进程中返回相同的起始地址? 如果没有,那么谁来处理这件事。 如果是,则两个进程都可以访问此地址的相同数据。

【问题讨论】:

  • 我们正在使用虚拟地址!

标签: c linux malloc virtual-memory


【解决方案1】:

malloc() 是否有可能在两个进程中返回相同的起始地址。

是的,但这不是问题。

您不了解的是,操作系统首先会为您处理物理空间 - 程序等只能看到虚拟地址。只有一个虚拟地址空间,但是,操作系统(让我们暂时坚持使用 32 位)将其划分。在 Windows 上,上半部分 (0xA0000000+) 属于内核,下半部分属于用户模式进程。这称为 2GB/2GB 拆分。在 Linux 上,划分为 3GB/1GB - 请参阅 this article:

内核内存定义为从 PAGE_OFFSET 开始,在 x86 中为 0XC0000000,即 3 GB。 (这是定义 3gig/1gig 拆分的地方。) PAGE_OFFSET 以上的每个虚拟地址都是内核,PAGE_OFFSET 以下的任何地址都是用户地址。

现在,当发生进程切换(与上下文切换相反)时,属于当前进程的所有页面都从虚拟内存中取消映射(不一定要对它们进行分页),并且所有属于待定进程的页面-run 进程被复制进来(免责声明:这可能并不完全正确;理论上可以将页面标记为脏等并在访问时复制)。

拆分的原因是,出于性能原因,虚拟内存空间的上半部分可以保持映射到操作系统内核。

因此,尽管 malloc 可能在两个给定进程中返回相同的值,但这并不重要,因为:

  1. 实际上,它们不是同一个地址。
  2. 这些进程不会在任何地方共享虚拟内存。

对于 64 位系统,由于我们目前只使用其中的 48 位,因此在用户模式的底部和内核模式之间存在一个鸿沟,目前还无法解决。

【讨论】:

  • 其实是3GB/1GB的拆分,0xc0000000是32位地址空间的最后一个千兆字节的起始地址。
  • @Benoit 在那种情况下,我填满了我的号码。在 Windows 上通常是 2GB/2GB 拆分,除非您明确要求它是 /LARGEADDRESSAWARE
  • 我不知道 Windows 的情况,请联系我们获取信息。我指出,因为 Linux 的内核空间开始于你提到的 0xc0000000。
  • @Benoit 这很重要 - OP 确实标记了他的 Q linux。我会更新,谢谢:)
  • 第四行,第二个“virtual”应该是“physical”吧?
【解决方案2】:

是的,malloc() 可以在不同的进程中返回相同的指针值,如果进程在不同的地址空间中运行,这是通过虚拟内存实现的。但在这种情况下,它们不会访问相同的物理内存位置,而且地址处的数据显然不必相同。

【讨论】:

    【解决方案3】:

    进程是线程和地址空间的集合。这个地址空间被称为 virtual 因为它的每个字节不一定由物理内存支持。如果进程中的应用程序最终有效地使用了该内存,则虚拟地址空间的段最终将由物理内存支持。

    因此,malloc() 可能会为两个进程返回相同的地址,但这没有问题,因为这些 malloced 内存将由不同的物理内存段支持。

    此外,malloc() 实现大部分不可重入,因此在共享相同地址空间的不同线程中调用 malloc() 希望不会导致返回相同的虚拟地址。

    【讨论】:

    • 两个线程调用malloc()不能同时修改bookeeping结构。一些机制会使malloc() 成为线程安全的,是的。
    • 正确,在 malloc()/free() 内部或外部。
    猜你喜欢
    • 2011-04-02
    • 2021-11-05
    • 1970-01-01
    • 2014-05-27
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多