【发布时间】:2012-07-04 22:36:04
【问题描述】:
假设我在 Linux 上有两个进程 a 和 b。在这两个过程中我都使用malloc() 来分配内存,
malloc() 是否有可能在两个进程中返回相同的起始地址?
如果没有,那么谁来处理这件事。
如果是,则两个进程都可以访问此地址的相同数据。
【问题讨论】:
-
我们正在使用虚拟地址!
标签: c linux malloc virtual-memory
假设我在 Linux 上有两个进程 a 和 b。在这两个过程中我都使用malloc() 来分配内存,
malloc() 是否有可能在两个进程中返回相同的起始地址?
如果没有,那么谁来处理这件事。
如果是,则两个进程都可以访问此地址的相同数据。
【问题讨论】:
标签: c linux malloc virtual-memory
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 可能在两个给定进程中返回相同的值,但这并不重要,因为:
对于 64 位系统,由于我们目前只使用其中的 48 位,因此在用户模式的底部和内核模式之间存在一个鸿沟,目前还无法解决。
【讨论】:
/LARGEADDRESSAWARE
是的,malloc() 可以在不同的进程中返回相同的指针值,如果进程在不同的地址空间中运行,这是通过虚拟内存实现的。但在这种情况下,它们不会访问相同的物理内存位置,而且地址处的数据显然不必相同。
【讨论】:
进程是线程和地址空间的集合。这个地址空间被称为 virtual 因为它的每个字节不一定由物理内存支持。如果进程中的应用程序最终有效地使用了该内存,则虚拟地址空间的段最终将由物理内存支持。
因此,malloc() 可能会为两个进程返回相同的地址,但这没有问题,因为这些 malloced 内存将由不同的物理内存段支持。
此外,malloc() 实现大部分不可重入,因此在共享相同地址空间的不同线程中调用 malloc() 希望不会导致返回相同的虚拟地址。
【讨论】:
malloc()不能同时修改bookeeping结构。一些机制会使malloc() 成为线程安全的,是的。