【问题标题】:Where is the stack memory allocated from for a Linux process?为 Linux 进程分配的堆栈内存在哪里?
【发布时间】:2013-07-14 07:57:45
【问题描述】:

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

【问题讨论】:

标签: linux unix operating-system


【解决方案1】:

我希望您知道所有用户进程将仅保存在用户空间中的概念。它使用系统调用来让内核完成一些工作。

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

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

cat /proc/1234/maps 将为您提供该特定进程的映射。

在该映射文件中,您可以检查stack 的堆栈映射。

【讨论】:

  • 您的回答提供了很好的洞察力,因为我不知道这些。我有一个小的澄清.. 堆栈大小是如何确定的(我们通常说 8 mb)?总是8mb吗?
  • ulimit -s 将给出您的默认堆栈大小。 stackoverflow.com/questions/14471564/… 了解更多。 :)
  • 感谢您的回答..!!
  • 但是当一个进程存在时,就会为它分配一个内核堆栈。那么这个进程堆栈和内核堆栈是相同的还是不同的?
【解决方案2】:

首先你必须了解什么是分页和页面错误:How does x86 paging work?

内核与进程内存

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

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

精确拆分由CONFIG_VMSPLIT_... 配置。默认情况下:

  • 在 32 位上:

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

    像这样:

    ------------------ FFFFFFFF
    Kernel
    ------------------ C0000000
    ------------------ BFFFFFFF
    
    
    Process
    
    
    ------------------ 00000000
    
  • 在 64 位上:当前仅实际使用 48 位,分成两个大小相等的不相交空间。 Linux 内核只是分配:

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

    像这样:

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

进程地址空间

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

------------------ <--- Top of the process address space
Stack (grows down)
v v v v v v v v v
------------------

(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的一个实际例子:What does brk( ) system call do?

这个答案解释了在可能的情况下使用堆栈的优势:What is the function of the push / pop instructions used on registers in x86 assembly?

物理记忆

内核和用户空间内存之间没有明确的划分:Is there an explict split between userspace and kernel in physical memory on Linux x86-64?

【讨论】:

    【解决方案3】:

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

    8 MB 实际上不是堆栈大小,而是 最大 堆栈大小。最初分配一小部分,内核在需要时(在页面错误之后)自动增长堆栈,使其低于堆栈大小限制。如果您执行超出限制的内存访问,则会出现分段错误。但是即使你没有达到这个限制,这意味着你可能仅仅通过填充堆栈就耗尽了物理内存(RAM +交换)。

    这是我在回复How does stack allocation work in Linux? 时给出的参考:Mel Gorman 的论文Understanding The Linux Virtual Memory Manager。请特别参阅第 4.6.1 节 处理页面错误,但“区域无效但位于像堆栈这样的可扩展区域旁边”和相应的操作“扩展区域并分配页面”除外。另请参阅 D.5.2 扩展堆栈

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-10
        • 1970-01-01
        • 2014-10-04
        • 1970-01-01
        • 2018-07-24
        • 1970-01-01
        • 2011-05-28
        相关资源
        最近更新 更多