自定义堆/内存分配范围

Posted

技术标签:

【中文标题】自定义堆/内存分配范围【英文标题】:Custom heap/memory allocation ranges 【发布时间】:2018-01-10 12:45:46 【问题描述】:

我正在 Linux 下用 C(使用 GCC)和 NASM 编写一个 64 位应用程序。

有没有办法指定我希望我的堆和堆栈位于何处。具体来说,我希望我所有的 malloc 数据都在 0x00000000-0x7FFFFFFF 范围内的任何地方。这可以在编译时、链接或运行时通过 C 代码或其他方式完成。没关系。

如果不可能,请解释原因。

附:对于那些感兴趣的人,我到底在做什么:

我正在开发的程序是用 C 语言编写的。在运行时,它会生成 NASM 代码,对其进行编译并动态链接到已经运行的程序。这是极端优化所必需的,因为该代码将运行数千甚至数十亿次,并且在编译时是未知的。所以我需要 0x00000000-0x7FFFFFFF 地址的原因是因为它们适合汇编代码中的立即数。如果我不需要单独加载地址,我可以将所需的内存访问次数减少一半并增加局部性。

【问题讨论】:

出于好奇:你为什么要这个? 你真的需要绝对即时吗?我读了你的隐形 PS,我正在考虑研究通常广泛的地址模式选择。难道没有一个可用的“立即+偏移”,其中偏移在寄存器中,被配置一次,然后使用与使用绝对立即数相同的时钟和字节数? @RuRo 如果您只想申请一些虚拟地址,可以查看mmap。使用MAP_ANONYMOUS,您应该获得地址。虽然我不是你可以在你指定的地址范围上使用它。内核可能被映射到那里。如果您对地址比较灵活,请使用更高的范围。 一方面每次分两步将 64 位加载到寄存器中并使用它(如您所描述的),另一方面设置偏移寄存器 once (或每次更改为汇编程序至少一次),然后使用该更改立即数(百万)次。后者的范围与使用绝对立即数相同,但“基数”适用于您分配内存的任何位置。 @RuRo MAP_ANONYMOUS - 映射没有任何文件支持;它的内容被初始化为零。 fd 参数被忽略;但是,如果 MAP_ANONYMOUS,某些实现要求 fd 为 -1——这就是手册页所说的。你必须在标志中传递这个。 【参考方案1】:

对于 Linux,获取任何虚拟地址范围的标准方法是使用 mmap(2) 函数。

您可以指定起始虚拟地址和大小。如果该地址尚未在使用中并且没有被先前的调用(或内核)保留,您将可以访问虚拟地址。

可以通过将返回值与您传递的起始地址进行比较来检查此调用是否成功。如果调用失败,函数返回NULL

一般mmap 用于将虚拟地址映射到文件描述符。但是这种映射必须通过 RAM 上的物理页面进行。由于应用程序无法直接访问磁盘。

由于您不需要任何文件支持,您可以在mmap 调用中使用MAP_ANONYMOUS 标志(也可以将-1 作为fd 传递)。

这是手册页相关部分的摘录-

MAP_ANONYMOUS

映射没有任何文件支持;它的内容是 初始化为零。 fd 参数被忽略;然而, 如果 MAP_ANONYMOUS (或 MAP_ANON) 被指定,并且可移植的应用程序应该 确保这一点。偏移量参数应该为零。指某东西的用途 支持 MAP_ANONYMOUS 和 MAP_SHARED Linux 仅从内核 2.4 开始。

【讨论】:

以上是关于自定义堆/内存分配范围的主要内容,如果未能解决你的问题,请参考以下文章

C 语言二级指针作为输入 ( 自定义二级指针内存 | 为 二级指针 分配内存 - 存放 一维指针 | 为每个 一级指针 分配内存 | 释放二维指针内存 )

C中动态内存分配器的自定义实现

检查指针是不是指向堆上分配的内存

C 语言二级指针作为输入 ( 自定义二级指针内存 | 二级指针排序 | 抽象业务逻辑函数 )

Java中堆内存与栈内存分配浅析

JAVA虚拟机内存分配与回收机制