【问题标题】:Memory available to assembly program in LinuxLinux 中汇编程序可用的内存
【发布时间】:2020-07-25 08:24:26
【问题描述】:

为了好玩,我只是想在带有 x86 处理器的笔记本电脑上为 Linux 编写一个汇编程序来获取一些系统信息。所以我试图找到的一件事是我的程序有多少内存可用,以及在哪里,例如堆栈是,如果需要,我是否以及如何分配额外的内存。

很久以前,我在 Atari ST 上做过类似的事情,只有一个系统“malloc”我可以从中请求内存,并且有一些函数可以找到可用内存。

我知道 Linux 的设置有所不同,而且我拥有自己的整个地址空间,但我想有些内存区域我是不允许触摸的。

不知何故,似乎已经设置了默认堆栈。

我对此进行了相当多的研究,但找不到任何“程序集”系统调用。大多数人指向链接 C malloc 进行内存管理,但我不是在寻找内存管理器。我只想知道我的程序的内存边界。

我发现诸如 getrlimit、setrlimit、prlimit 和 brk 和 sbrk 之类的东西,但这些似乎是 C 函数而不是系统调用。

我错过了什么?

【问题讨论】:

  • 这些区域在现代系统上并不固定。您可以查看文件/proc/self/maps 以查找堆栈位置和大小。 /proc 文件系统中可能还有其他文件,以及系统调用,以查找其他事物的映射。
  • 您可以在程序的可执行文件中指定初始内存映射。在运行时,您可以使用mmapmunmap 系统调用修改此内存映射。根据经验,UNIX 手册第 2 节中列出的每个 C 函数都是系统调用。所有这些都可以直接从程序集中调用,而无需使用 libc,尽管使用 libc 通常是个好主意。

标签: linux assembly system-calls


【解决方案1】:

Linux 使用虚拟内存(和ASLR)。 Atari ST 不使用任何一种,因此它确实为某些 OS 数据结构和代码提供了固定的内存映射。 (由于操作系统在ROM中,不易更新,甚至有人记录了一些内部地址。)

Linux 试图保持内核和用户空间之间的严格界限,使用定义良好的文档 API / ABI 供用户空间通过系统调用与内核交互。 (例如,在 x86-64 上,通过 syscall 指令)。用户空间不需要关心那堵墙的另一边是什么,通常甚至不需要关心它的页面在虚拟内存中的位置,只要它有指向它们的指针。

当 glibc malloc 想要更多来自操作系统的页面时,它使用mmap(MAP_ANONYMOUS)brk 来获取它们,并将它们的大块分发给malloc 的小调用。它将簿记数据结构保存在用户空间中(当然这是每个进程)。

我知道 Linux 的设置有所不同,而且我拥有自己的整个地址空间,但我想有些内存区域我是不允许触摸的。

是的,每个进程都有自己的虚拟地址空间。您只能触摸已分配的部分,否则导致的页面错误将是“无效的”(操作系统知道该虚拟页面不应该是物理页面)并且如果您将 SIGSEGV 信号传递给您的进程试着读或写它。 (“有效”页面错误是由于交换空间或延迟分配/写时复制而发生的;内核更新硬件页表并返回用户空间以重新运行出错的指令。)

此外,内核声称虚拟地址空间的高半部分供自己使用。 (https://wiki.osdev.org/Higher_Half_Kernel)。另请参阅https://www.kernel.org/doc/Documentation/x86/x86_64/mm.txt,了解 Linux 的 x86-64 内存映射布局。

我找不到任何“程序集”系统调用。

mmapbrk 是真正的系统调用。请参阅brk(2) man page 的“注释”部分。第 2 节手册页是系统调用,第 3 节是 libc 函数。

当然,在 C 中调用 mmap(...) 时,实际上是在调用 glibc 中的包装函数。 glibc 提供包装函数,而不是直接使用 syscall 指令的内联 asm 宏。

另请参阅The Definitive Guide to Linux System Calls,它解释了 asm 接口以及 VDSO 页面。 Linux 将一些内核内存(只读)映射到您的用户空间进程,保存代码和数据,以便 getpid()clock_gettime() 可以在用户空间中运行。

还有关于 Stack Overflow 的各种问答,包括What are the calling conventions for UNIX & Linux system calls on i386 and x86-64


所以我试图找到的一件事是我的程序可以使用多少内存

没有系统调用来查询进程的当前内存映射。解析/proc/self/maps 将是您最好的选择。

有关使用系统调用扫描映射页面的虚拟地址空间范围的一些有趣想法,请参阅Finding mapped memory from inside a process。例如就像 Linux 的 mincore(2) syscall 如果指定范围包含任何未映射的页面,则返回 -ENOMEM

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-08
    • 2011-03-19
    相关资源
    最近更新 更多