从Linux进程分配的堆栈内存在哪里?

我们知道当创build一个进程时,为这个进程分配一个堆栈。在linux中,堆栈的大小通常是8Mb。我的问题是,从这个堆栈分配的位置?从用户空间还是从系统空间?

Solutions Collecting From Web of "从Linux进程分配的堆栈内存在哪里?"

我希望你知道所有的用户进程只保留在用户空间的概念。 它使用系统调用来完成内核完成的一些工作。

堆栈内存将成为内存中进程上下文区域的一部分。 即用户空间

假设你的进程正在运行,通过ps -ax获取PID。 说1234是你的PID。

cat /proc/1234/maps会给你这个特定进程的映射。

在那个映射文件中,您可以检查堆栈映射。

正如别人所说,堆栈分配在用户空间。 但是这里有更多的细节,特别是关于它的规模和增长。

8 MB实际上不是堆栈大小,而是最大的堆栈大小。 一小部分最初被分配,内核在需要的时候自动增长堆栈(在一个页面错误之后),使其保持在堆栈大小限制之下。 如果你的内存访问超过限制,你会得到一个分段错误。 但是即使你没有达到这个限制,这意味着你可能会耗尽物理内存(RAM + swap),只是填满堆栈。

下面是我在回答中给出的一个参考: 在Linux中堆栈分配是如何工作的? Mel Gorman的文章了解Linux虚拟内存管理器 。 特别参见4.6.1 处理页面错误 ,除了“区域无效但在可扩展区域旁边,像堆栈”以及相应的操作“扩展区域并分配页面”。 另请参阅D.5.2 展开堆栈

首先,您必须了解页面和页面错误: x86分页如何工作?

内核vs进程内存

Linux内核保留两个虚拟内存区域:

  • 一个用于内核内存
  • 一个用于程序

精确的分割由CONFIG_VMSPLIT_...配置。 默认:

  • 在32位上:

    • 底部3/4是程序空间: 00000000BFFFFFFF
    • 最高的1/4是内核内存: C0000000FFFFFFFF

    喜欢这个:

     ------------------ FFFFFFFF coreel ------------------ C0000000 ------------------ BFFFFFFF Process ------------------ 00000000 
  • 在64位上:目前实际上只使用了48位,被分割成两个大小不相等的空格。 Linux内核只分配:

    • 底部处理00000000 00000000008FFFFF FFFFFFFF
    • 内核的顶部: FFFF8000 00000000FFFFFFFF FFFFFFFF

    喜欢这个:

     ------------------ FFFFFFFF FFFFFFFF coreel ------------------ FFFF8000 00000000 (not addressable) ------------------ 008FFFFF FFFFFFFF Process ------------------ 00000000 00000000 

进程地址空间

一个进程的简化程序虚拟内存:

 ------------------ <--- Top of the process address space Stack (grows down) vvvvvvvvv ------------------ (unmapped) ------------------ <--- Maximum stack size. (unmapped) ------------------- mmap ------------------- (unmapped) ------------------- ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ brk (grows up) ------------------- BSS ------------------- Data ------------------- Text ------------------- ------------------- <--- Bottom or process address space. 

堆栈分配

内核维护属于每个进程的页面列表,并将其与分页进行同步。

如果程序访问不属于它的内存,内核将处理页面错误,并决定要执行的操作:

  • 如果它高于最大堆栈大小,则将这些页面分配给进程
  • 否则,发送一个SIGSEGV给进程,通常会杀死它

更多信息: https : //unix.stackexchange.com/questions/145557/how-does-stack-allocation-work-in-linux/239323#239323

brkmmap

这些系统调用允许进程向内核显式地请求内存块,而不是仅仅停留在堆栈和段之间。

这里是一个brk的实际例子: brk()系统调用是做什么的?

这个答案解释了在可能的情况下使用堆栈的好处: 在x86程序集的寄存器中使用的push / pop指令的功能是什么?

物理内存

在内核和用户空间内存之间没有明确的划分: 在Linux x86-64的物理内存中,用户空间和内核之间是否存在显式拆分?

应用软件所需的堆栈内存是从用户空间分配的。