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

时间:2013-07-16 08:18:41

标签: linux unix operating-system

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

4 个答案:

答案 0 :(得分:5)

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

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

假设您的流程正在运行,请按ps -ax获取PID。比如1234就是你的PID。

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

在那个map文件中,你可以检查stack的堆栈映射。

答案 1 :(得分: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 扩展堆栈

答案 2 :(得分:3)

首先,您必须了解分页和页面错误: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

这些系统调用允许进程显式地向内核请求内存块,而不是仅仅向下移动堆栈和segfaulting。

以下是brkWhat 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 :(得分:0)

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