在64位Linux操作系统上运行的32位进程的内存限制

13

在64位Linux上,32位进程可以拥有多少虚拟内存空间(即在使用malloc()分配内存之前可以分配和使用多少内存,而不会得到空指针错误)?

我在我的32位Linux上尝试过,达到了约3 GB的限制。在64位Linux上能否获得更多内存?

4个回答

26
在标准的32位x86 smp内核中,每个进程可以使用4GB地址空间中的3GB,1GB由内核使用(在每个进程的地址空间共享)。
使用4G/4G分割的“hugemem” 32位x86内核,每个进程可以使用(几乎)整个4GB的地址空间,内核有一个单独的4GB地址空间。Red Hat在RHEL 3和4中支持了这个内核,但在RHEL 5中放弃了它,因为补丁没有被合并到主线内核中,现在大多数人都使用64位内核了。
在64位x86_64内核中,32位进程可以使用整个4GB地址空间,除了4GB地址空间末尾的一些页面(8KB),它们由内核管理。内核本身使用位于32位代码无法访问的地址空间的一部分,因此不会减少用户地址空间。64位进程可以使用更多的地址空间(在RHEL 6中为128TB)。
请注意,一些地址空间将被程序代码、库和堆栈空间使用,所以您将无法使用malloc()来分配整个地址空间。这些东西的大小因程序而异。查看/proc/<pid>/maps以查看进程中如何使用地址空间;您可以使用最大未使用地址范围来限制malloc()的数量。

如果在64位操作系统/内核中有两个或三个32位进程怎么办呢? 假设一个服务器有64GB内存运行64位内核。 那么所有32位进程是否都将被限制在4GB内存块中,还是每个进程都有独立的4GB限制? 如果是前者,则三个独立的32位进程都将受到相同的4GB内存块的限制;如果是后者,则每个32位进程将被限制为4GB,使得32位进程使用的总内存高达12GB。哪一个是正确的? - Tagar
2
有了64位内核,每个32位进程都可以拥有自己独立的4GB虚拟内存。这并不一定对应所需的物理RAM总量;一些处于非活动状态的虚拟内存可能会被分页到磁盘上。 - mark4o
谢谢您的跟进。关于共享库呢?每个 32 位共享库会在每个 32 位进程的“自己”的 4GB 空间中被复制吗?还是一个 32 位共享库的实例将被不同的 32 位进程使用,每个进程都有自己的 4GB 空间? - Tagar
2
如果同一共享库(或其他文件)的相同部分被映射为只读到不同进程的虚拟地址空间中,则它们可以在物理内存中共享一个副本,即使该文件在每个进程中映射到不同的虚拟地址。对写入的初始化数据部分将为每个进程有一个单独的副本。 - mark4o

2

如上所述,32位内核上的32位进程能够分配大约3GB左右的内存。64位内核上的32位进程则能够分配大约4GB左右的内存。


1
一个32位的进程无论在什么操作系统下,只能访问4GB的虚拟内存。这是因为该进程只能映射32位的内存地址。如果你做一下数学计算,你会发现32位地址最多只能访问4GB的内存,即使你运行在128位的操作系统上也是如此。

这没问题,但并没有回答我的问题。 我能在64位Linux上获得最大的4GB吗? - leonidp
1
请注意,在Linux上,内核会保留大约1GB的内存供自己使用,因此用户空间进程只能访问3GB的内存。 - Kristof Provost
1
@leonidp 实际上它回答了这个问题。简短的版本是“不”。 - Kristof Provost
@Kristof 好的,让我们看看我是否理解正确。在64位Linux上,我将获得最大4GB的内存,但由于内核保留了1GB的内存,因此我实际上只能获得3GB? 那么,对我来说,32位或64位Linux没有区别? - leonidp
2
@leonidp:使用本地64位程序,以便为您的用户空间程序使用超过2GB / 3GBytes的虚拟内存。 - Yann Droneaud

0
在64位Linux上,单个进程的最大内存空间为2^48字节。(理论上,更多是可能的,但当前的芯片不允许使用整个2^64字节的虚拟地址空间。)
请参阅维基百科获取更多信息。

2
是的,我知道。但是我有一个32位的进程,所以无论操作系统是否为64位,它都被限制在4GB内(是吗?)。那么,在64位Linux上我真的会获得这个最大值吗?(现在,在32位Linux上我只获得3GB) - leonidp
1
@leonidp 是的,你说得对。即使在64位Linux上,32位进程也不能使用更多的内存。你需要为64位重新构建你的应用程序。 - dogbane

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接