Linux上的clone()系统调用接受一个指向堆栈的参数,以供新创建的线程使用.显而易见的方法是简单地malloc一些空间并传递它,但是你必须确保你已经使用了大量的堆栈空间,因为该线程将使用(很难预测).
我记得在使用pthreads时我不必这样做,所以我很好奇它做了什么.我遇到了这个网站,它解释说,"Linux pthreads实现使用的最佳解决方案是使用mmap来分配内存,标志指定在使用时分配的内存区域.这样,内存分配给根据需要使用堆栈,如果系统无法分配额外的内存,则会发生分段违规."
我曾经听过mmap使用的唯一上下文是将文件映射到内存,实际上读取mmap手册页需要一个文件描述符.如何使用它来分配一堆动态长度来给clone()?这个网站真的很疯狂吗?;)
在任何一种情况下,内核都不需要知道如何为新堆栈找到一堆免费内存,因为在用户启动新进程时,它必须始终做什么?如果内核已经能够解决这个问题,为什么首先需要首先指定堆栈指针?
我正在学习amd64汇编程序,并尝试实现一个简单的Unix过滤器。由于未知的原因,甚至简化为最低版本(下面的代码),它也会随机崩溃。
我试图在GNU调试器(gdb)中调试该程序。在gdb的默认配置中,该程序运行良好,但是如果启用地址随机化(set disable-randomization off),该程序将开始崩溃(SIGSEGV)。清单中标记了有问题的说明:
format ELF64 executable
sys_read = 0
sys_write = 1
sys_exit = 60
entry $
foo:
label .inbuf at rbp - 65536
label .outbuf at .inbuf - 65536
label .endvars at .outbuf
mov rbp, rsp
mov rax, sys_read
mov rdi, 0
lea rsi, [.inbuf]
mov rdx, 65536
syscall
xor ebx, ebx
cmp eax, ebx
jl .read_error
jz .exit
mov r8, rax ; r8 - count of valid bytes in input buffer
xor r9, r9 ; …Run Code Online (Sandbox Code Playgroud) 我试图创建MAP_GROWSDOWN映射,期望它会自动增长。如手册页中所述:
MAP_GROWSDOWN
此标志用于堆栈。它向内核虚拟内存系统指示映射应该在内存中向下扩展。返回地址比在进程的虚拟地址空间中实际创建的内存区域低一页。 触摸映射下方“守卫”页面中的地址会导致 映射增长一页。这种增长可以重复,直到映射增长到下一个较低映射的高端页面内,此时触摸“保护”页面将产生
SIGSEGV信号。
所以我写了下面的例子来测试映射的增长:
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <errno.h>
#include <sys/mman.h>
#include <stdio.h>
int main(void){
char *mapped_ptr = mmap(NULL, 4096,
PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_STACK | MAP_GROWSDOWN,
-1, 0);
if(mapped_ptr == MAP_FAILED){
int error_code = errno;
fprintf(stderr, "Cannot do MAP_FIXED mapping."
"Error code = %d, details = %s\n", error_code, strerror(error_code));
exit(EXIT_FAILURE);
}
volatile char *c_ptr_1 = mapped_ptr; //address returned by mmap
*c_ptr_1 …Run Code Online (Sandbox Code Playgroud) 我想知道变量的初始化方式:
#include <stdio.h>
int main( void )
{
int ghosts[3];
for(int i =0 ; i < 3 ; i++)
printf("%d\n",ghosts[i]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这给我带来了随机值,例如 -12 2631 131 ..它们来自哪里?
例如,x86-64 Linux 上的 GCC:https ://godbolt.org/z/MooEE3ncc
我有一个猜测来回答我的问题,无论如何它都可能是错误的:
内存的寄存器在“清空”后获得 0 和 1 之间的随机电压,这些值“四舍五入”为 0 或 1,并且这些随机值取决于在某事上?!也许寄存器的制作方式?也许内存的容量会以某种方式发挥作用?甚至可能是温度?!!
我浏览了一段时间,试图例如在执行操作时了解如何将内存分配给堆栈:
push rax
Run Code Online (Sandbox Code Playgroud)
或者移动堆栈指针为子例程的局部变量分配空间:
sub rsp, X ;Move stack pointer down by X bytes
Run Code Online (Sandbox Code Playgroud)
据我了解,堆栈段在虚拟内存空间中是匿名的,即不是文件支持的。
我还了解的是,内核不会真正将匿名虚拟内存段映射到物理内存,直到程序对该内存段进行实际操作(即写入数据)为止。因此,尝试在写入该段之前先读取该段可能会导致错误。
在第一个示例中,如果需要,内核将在物理内存中分配一个帧页。在第二个示例中,我假设内核不会在程序实际将数据写入堆栈堆栈段中的地址之前将任何物理内存分配给堆栈段。
我在正确的轨道上吗?
我正在阅读有关内存过度使用的页面,其中提到
The C language stack growth does an implicit mremap. If you want absolute
guarantees and run close to the edge you MUST mmap your stack for the
largest size you think you will need. For typical stack usage this does
not matter much but it's a corner case if you really really care
Run Code Online (Sandbox Code Playgroud)
当程序编译时(例如通过gcc),定义了堆栈的大小限制(我记得有一个gcc参数可以调整它)。然后,在程序内部,我们可以继续在堆栈上分配。
几个问题:
mremap()会在幕后调用?为什么如果在编译时就定义了堆栈的大小限制呢?mmap堆栈呢?In the x86-64 System V ABI it is specified that the space behind the $rsp - 128 is the so-called red zone which is not touched by any signal handlers. On my machine
$ ulimit -s
8192
Run Code Online (Sandbox Code Playgroud)
I expected there is only 2 pages in the stack. So I wrote the following program to test till which size red zone can expand:
PAGE_SIZE equ 0x1000
SYS_exit equ 0x3C
section .text
global _start
_start:
lea rcx, [rsp - 0x1f * PAGE_SIZE] …Run Code Online (Sandbox Code Playgroud) 我正在使用堆栈进行一些实验,以下内容让我陷入困境。
可以看出Linux在大小上有初始[stack]映射132KiB。ulimit -s unlimited如果我们进行相应的调整,我们可以进一步扩展堆栈rsp。所以我设置ulimit -s unlimited并运行了以下程序:
PAGE_SIZE equ 0x1000
;mmap staff
PROT_READ equ 0x01
PROT_WRITE equ 0x02
MAP_ANONYMOUS equ 0x20
MAP_PRIVATE equ 0x02
MAP_FIXED equ 0x10
;syscall numbers
SYS_mmap equ 0x09
SYS_exit equ 0x3c
section .text
global _start
_start:
; page alignment
and rsp, -0x1000
; call mmap 0x101 pages below the rsp with fixed mapping
mov rax, SYS_mmap
lea rdi, [rsp - 0x101 * PAGE_SIZE]
mov rsi, PAGE_SIZE
mov …Run Code Online (Sandbox Code Playgroud)