在Linux系统中,每个进程都被赋予了一个4GB的虚拟地址空间,这是基于32位体系结构的。

3

你好,我是新手Linux内核开发者。所以想要对以下陈述有一些清晰的理解。

*> 在内存中,每个进程被赋予4GB的虚拟地址空间

考虑到32位架构。低3GB虚拟地址可以访问进程的用户空间部分,而高1GB可以访问内核空间部分。

  1. 这是否意味着Linux中的每个进程都被分配了1GB+3GB的内存空间?
  2. 如果是的话,那么Linux中有数百个进程,系统从哪里获得如此多的内存空间?
  3. 它与内核栈和用户栈有什么关系?
  4. Linux中的每个进程是否都有内核和用户栈?

3
你应该学习虚拟内存是如何工作的。计算机有实际的物理内存(即RAM),还有一种叫做虚拟内存的映射方式(指向可能存在或不存在的RAM)。4GB是映射的限制,不必完全使用。 - myaut
2个回答

3

介绍

Linux和大多数现代操作系统一样,使用由大多数现代架构提供的虚拟页。其中包括x86系列。

在具有虚拟内存的系统中,物理内存(实际RAM资源)与运行在系统上的进程是相互独立的。地址空间只是内存可能存在的所有数字。

分页

内存可以映射(放置在一个地址上)到页面,它是内存块的体系结构相关大小。因此,如果您想将内存放置在某个地址上以便进程可以使用它,那么您必须选择一个对齐页面的数字(页面大小的倍数),并至少在那里放置一个页面。

保护

虚拟内存也允许内存保护,从而设置进程将具有的权限。当映射进程的可执行内存(执行操作的指令)时,它是只读/执行的。这意味着处理器可以执行该内存,您可以读取它,但是您不能写入它。

当从磁盘加载进程时(在Linux中使用exec系统调用),它会被放置在内存中,已经映射了几个内存区域。这些区域是程序的可执行代码、数据部分和堆栈。进程可以通过使用mmapbrk系统调用来请求映射更多内存。

当进程尝试访问它没有映射的内存时,它会触发臭名昭著的SEGFAULT错误,并且内核将终止您的程序。其他情况下,硬件会发生故障,但程序已经有了映射的内存,这是因为内核取消了映射以将其保存到需要时再重新映射。在这里发生的情况是进程停止运行,内核重新映射内存,您的进程再次开始运行,就像什么都没发生过一样。

地址空间

因此,地址空间的大小只是如果程序将每个可能的地址都映射到实际RAM内存,则内存的上限。

内核部分的1GB地址空间与内核跟踪的进程元数据有关。例如,它将在进程标题中保留打开的文件列表和映射内存。它还将在那里保留线程标题。同样,仅映射所需的内容,而不是全部。

请注意,每个进程都有自己的地址空间,它从不看到其他进程在这些地址上映射了什么。这样,进程可以像是机器上唯一的进程一样运行,将内存映射到任何所选地址。

还要注意,4GB数字是因为进行寻址的硬件仅支持32位数字,32位数字可以容纳的最大数字是2^32= 4,294,967,296。这是4GB。因此,只能将4GB的地址映射到内存中。

这只是一个糟糕的介绍,请在虚拟内存上做一些搜索。


@Dpk 关于堆栈大小的问题。我认为你可能在考虑8MB,这是内核对堆栈大小的限制。当程序启动时,它会被分配一些页面用于堆栈。为了节省内存,它不会立即映射所有的堆栈页面,而是会随着堆栈的增长而增长。堆栈位于高地址,并向低地址增长。当你的程序尝试访问低于内核已映射内存的内存时,内核将映射更多的内存(与“SEGFAULT”硬件中断相同,只是内核将映射更多的内存)。也就是说,直到达到一个限制(8MB)。 - cptaffe
@Dpk 还要注意,内核1GB被映射到相同的内核RAM内存(一些是特定于核心的)(可能并非全部都被映射,内核可能比1GB小,或者有些可能没有分页)。还要注意,内核可以将内存分页到磁盘中进行换入/换出。因此,在进程切换之间未映射的内存会发生这种情况。其中一些可能会保留在内存中,一些可能会在许多进程之间共享(例如共享库)。 - cptaffe
如果每个进程都尝试映射一堆内存,直到使用时许多进程实际上不会被分页。一旦可用的内存资源(RAM和磁盘(交换))耗尽,OOM(内存不足)杀手就会介入并杀死进程。当太多的Chrome标签页杀死Spotify或其他东西时,在较小的内存系统上实际上经常发生这种情况。此外,一旦实际的RAM内存用完,将使用更多的交换空间。(对于长评论链感到抱歉) - cptaffe
还有一个问题,如何知道进程线程用户栈的大小。如果一个进程有大约400MB的数据,另一个进程有800MB的数据,还有其他一些进程,那么操作系统会如何暂存这些数据。 例如,如果一个Firefox被换出,则它认为3GB的空间只分配给了自己, 如果Chrome进来了,它会先将Firefox换出并将其暂存。 那么Firefox的数据在哪里暂时存储,以便在未来再次换入时可以使用? - Dpk
@Dpk 如果我理解正确,您正在询问当一个进程被换出时存储在内存中的数据会发生什么。如果Chrome和Firefox都使用了几乎所有可用的内存(约3GB),那么操作系统不能像在有多余内存的情况下那样将其留在RAM中但未映射到进程。在这种情况下,操作系统将内存交换到磁盘上,使用交换分区或交换文件。这就是为什么一个进程可以使用3GB的内存,即使您的系统只有2GB的RAM,操作系统会根据需要进行交换(尽管交换需要时间,因此速度会慢一些)。 - cptaffe
显示剩余4条评论

0
这是关于编程的内容。每个进程在Linux中被分配了1GB+3GB的内存空间吗?不是的。所有进程共享同一内核空间。此外,这些是最大理论限制。它们可以通过系统设置、进程设置和页面文件大小进一步限制。即使系统允许进程增长到最大值,进程通常也会从小开始,并且必须增长到达到最大值。
如果是这样,那么Linux中有数百个进程,那么系统从哪里获取如此多的内存空间呢?请参见上文。如果允许,这样的内存空间将在页面文件(分区)中。
这与内核堆栈和用户堆栈有什么关系?它们是独立的堆栈。内核堆栈位于内核空间,用户堆栈位于用户空间。处理器在内核模式下执行时使用内核堆栈,在用户模式下使用用户堆栈。切换是自动的,作为硬件在模式之间切换的一部分。
Linux中的每个进程都有内核和用户堆栈吗?是的。每个线程都有一个。内核堆栈往往很小。

内核栈大小限制为8KB的原因是什么?它与1GB空间有什么关系?另外,如何知道进程用户堆栈的大小? - Dpk
我相信Linux将内核栈限制为2页(8KB)。内核栈执行的是相对简单的操作,因此不需要太大。所有内核栈都位于1GB系统空间内。线程或进程的堆栈大小可以更改。 - user3344003
如何在Linux中了解进程/线程的用户栈大小。 - Dpk

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