c - 我是否必须将映射的长度添加到 mmap 返回的带有 MAP_GROWSDOWN 和 MAP_STACK 标志的指针?

标签 c linux mmap

我正在为 a.out 加载器创建一个简单的堆栈,我想出了这个:

stack = (char *)mmap(NULL,
                     65535,
                     PROT_READ | PROT_WRITE,
                     MAP_PRIVATE | MAP_STACK |
                       MAP_GROWSDOWN | MAP_UNINITIALIZED |
                       MAP_ANONYMOUS,
                     -1,
                     0);

但是,我不确定这一点。

在将结果指针移动到堆栈指针之前,我是否必须将 65535(映射的大小)添加到它,因为我使用了 MAP_STACKMAP_GROWSDOWN 标志?或者我可以直接使用它吗?

这方面的文档一直不是很清楚,我在网上搜索也没有找到任何东西。

具体来说,这个(来自 mmap(2))让我感到困惑:

The return address is one page lower than the memory area that is actually created in the process's virtual address space.

最佳答案

  1. 是的,您必须将 65536 添加到结果指针。注意,不是 65535。大多数架构将 push(x) 实现为 *--sp = x;所以让 sp above 堆栈是可以开始的。更重要的是它必须对齐,而 65535 不是。

  2. 文档似乎有误。我认为它的意图是“比……高出一页”。这更好地与源实现以及下面的小示例程序的结果保持一致:


  #include <signal.h>
  #include <stdio.h>
  #include <unistd.h>
  #include <sys/mman.h>

  volatile int sp;

  void segv(int signo) {
          char buf[80];
          int n = snprintf(buf, 80, "(%d): sp = %#x\n", signo, sp);
          write(1, buf, n);
           _exit(1);
  }

  int main(void) {
          int N = 65535;
          signal(SIGSEGV, segv);
          signal(SIGBUS, segv);
          char *stack = (char *)mmap(NULL,
                       N,
                       PROT_READ | PROT_WRITE,
                       MAP_PRIVATE | MAP_STACK |
                         MAP_GROWSDOWN | /*MAP_UNINITIALIZED |*/
                         MAP_ANONYMOUS,
                       -1,
                       0);
          printf("stack %p\n", stack);
          for (sp = 0; sp < N; sp += 4096) {
                  if (stack[sp]) {
                          printf("stack[%d] = %x\n", sp, stack[sp]);
                  }
          }
          for (sp = 0; sp > -N; sp -= 4096) {
                  if (stack[sp]) {
                          printf("stack[%d] = %x\n", sp, stack[sp]);
                  }
          }
          return 0;
  }

打印出:

$ ./a.out
stack 0x7f805c5fb000
(11): sp = -4096

在我的系统上:

$ uname -a
Linux u2 4.15.0-42-generic #45-Ubuntu SMP Thu Nov 15 19:32:57 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

关于c - 我是否必须将映射的长度添加到 mmap 返回的带有 MAP_GROWSDOWN 和 MAP_STACK 标志的指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56822176/

相关文章:

linux - 使用 bash 访问 getopts 选项中的第二个参数

c - 为什么我们可以分配一个 1 PB (10^15) 的数组并访问最后一个元素,但不能释放它?

c - 如果禁用 ASLR,mmap 是否具有确定性?

c - 使用 mmap 将文件投影到内存中

c - 复数数组的 FFT

c - ATmega328p,定时器0中断

c - Linux 下的 TCP 客户端/服务器

c - C 中的 fork 线程正在互相写入标准输出

c - 如何在日志文件中引入日期和时间

linux - python脚本通过传递参数来检查磁盘空间