我们知道,当创建一个进程时,会为该进程分配一个堆栈。堆栈的大小在 linux 中通常为 8 Mb。我的问题是,这个堆栈是从哪里分配的?从用户空间还是从系统空间?
4 回答
我希望您知道所有用户进程将仅保留在用户空间中的概念。它使用系统调用来让内核完成一些工作。
堆栈内存将成为内存中进程上下文区域的一部分。即用户空间。
假设您的进程正在运行,则通过 获取 PID ps -ax
。说 1234 是你的 PID。
cat /proc/1234/maps
将为您提供该特定过程的映射。
在 thats maps 文件中,您可以检查stack
堆栈映射。
首先您必须了解什么是分页和页面错误:x86 分页是如何工作的?
内核与进程内存
Linux 内核保留了两个虚拟内存区域:
- 一个用于内核内存
- 一个用于程序
确切的拆分由 配置CONFIG_VMSPLIT_...
。默认:
在 32 位上:
- 底部 3/4 是程序空间:
00000000
到BFFFFFFF
- 前 1/4 是内核内存
C0000000
:FFFFFFFF
像这样:
------------------ FFFFFFFF Kernel ------------------ C0000000 ------------------ BFFFFFFF Process ------------------ 00000000
- 底部 3/4 是程序空间:
关于 64 位:目前仅实际使用 48 位,分成两个大小相等的不相交空间。Linux 内核只是分配:
00000000 00000000
处理的底部008FFFFF FFFFFFFF
- 内核的顶部:
FFFF8000 00000000
到FFFFFFFF 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,这通常会杀死它
brk
和mmap
这些系统调用允许进程显式地向内核请求内存块,而不仅仅是向下堆栈和段错误。
下面是一个实际的例子brk
:brk() 系统调用是做什么的?
这个答案解释了在可能的情况下使用堆栈的优势:x86 汇编中寄存器上使用的 push / pop 指令的功能是什么?
物理内存
内核和用户空间内存之间没有明确的划分:Linux x86-64 上物理内存中的用户空间和内核之间是否有明确的划分?
正如其他人所说,堆栈是在用户空间中分配的。但这里有更多关于这一点的细节,特别是关于它的规模和增长。
8 MB 实际上不是堆栈大小,而是最大堆栈大小。最初分配一小部分,内核在需要时(在页面错误之后)自动增长堆栈,使其低于堆栈大小限制。如果您执行超出限制的内存访问,则会出现分段错误。但即使你没有达到这个限制,这意味着你可能仅仅通过填充堆栈就耗尽了物理内存(RAM +交换)。
这是我在回答堆栈分配如何在 Linux 中工作?:Mel Gorman 的论文了解 Linux 虚拟内存管理器。特别参见第 4.6.1 节处理页面错误,除了“区域无效,但在像堆栈这样的可扩展区域旁边”和相应的操作“扩展区域并分配页面”。另见 D.5.2扩展堆栈。
应用软件所需的堆栈内存是从用户空间分配的。