[英]Force memory allocation to allocate from higher address (>4GB) on 64-bit Linux
Here're what I want to do: I have a library built for 64-bit Linux. 我要做的是:我有一个为64位Linux构建的库。 Then I created an application linking that library. 然后,我创建了一个链接该库的应用程序。 I want to make sure when I run the application, the memory allocated from the library is always in the higher location (>4GB). 我想确保在运行应用程序时,从库分配的内存始终位于较高的位置(> 4GB)。
On Windows, user can force allocations to allocate from higher addresses before lower addresses for testing purposes, specify MEM_TOP_DOWN when calling VirtualAlloc or set the following registry value to 0x100000: 在Windows上,出于测试目的,用户可以强制分配从高地址开始分配,然后从低地址开始分配,以进行测试,在调用VirtualAlloc时指定MEM_TOP_DOWN或将以下注册表值设置为0x100000:
HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Memory Management\\AllocationPreference HKEY_LOCAL_MACHINE \\ System \\ CurrentControlSet \\ Control \\ Session Manager \\ Memory Management \\ AllocationPreference
I wonder if there's similar strategy on Linux. 我想知道Linux上是否有类似的策略。 I understand the Linux memory management is different than Window, but I found some clue such as using mmap() or linker scripts. 我了解Linux内存管理与Window不同,但是我发现了一些线索,例如使用mmap()或链接描述文件。 But I haven't been able to achieve the goal. 但是我没有达到目标。 Anybody could provide more information? 有人可以提供更多信息吗?
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main()
{
void *addr1=0, *addr2=0;
long sz = sysconf(_SC_PAGE_SIZE); // get page size
size_t length = sz*1000*1000; // 1,000,000 pages
int fd = -1;
printf("page size = %ld\n", sz);
// find some available address
int *p = (int*)malloc(sizeof(int));
long start = (long)p + sizeof(int);
free(p); // free it anyway
start += (sz-(start % sz)); // page alignment
printf("start = 0x%lx\n", start);
// mmap fixed
addr1 = mmap((void*)start, length, PROT_NONE,
MAP_PRIVATE|MAP_NORESERVE|MAP_ANONYMOUS|MAP_FIXED, fd, 0);
if (addr1 == MAP_FAILED)
handle_error("mmap");
printf("first map: %tx\n", addr1);
//msync(addr1, length, 0);
// another mmap
addr2 = mmap(NULL, sz*10, PROT_NONE,
MAP_ANONYMOUS|MAP_PRIVATE, fd, 0);
if (addr2 == MAP_FAILED)
handle_error("mmap");
printf("second map: 0x%tx\n", addr2);
// test whether the memory is still available
p = (int*)malloc(sizeof(int)*10);
printf("allocated address: 0x%tx\n", p);
return 0;
}
Output: 输出:
page size = 4096
start = 0x1d77000
first map: 1d77000
second map: 0x7f5f26c2f000
allocated address: 0x1d76030
I don't understand why you want to do that (avoiding mmap
giving some address in the first four gigabytes). 我不明白您为什么要这样做 (避免mmap
在前四个GB中提供一些地址)。
Hoever, you could, very early in your program -eg start of main
, or even some constructor function- call mmap(2) with MAP_FIXED
and MAP_NORESERVE
on several memory segments to achieve your goal; 但是,您可以在程序的早期-例如main
开始,甚至是一些构造函数-在几个内存段上使用MAP_FIXED
和MAP_NORESERVE
调用mmap(2)来实现目标; so you would ensure that all the address space below 4G would be "filled" -either by pre-existing segments of your programs, or by your such calls to mmap
. 因此,您可以确保通过预先存在的程序段或对mmap
的此类调用来“填充” 4G以下的所有地址空间。
However, your library (which could be indirectly dlopen
-ed) could be started much after the program. 但是,您的库(可以是间接dlopen
-ed)可以在程序之后启动。
Once the first four gigabytes are used in the address spaces, most ordinary mmap
calls (those done by malloc
for example) would go outside. 一旦在地址空间中使用了前四个千兆字节,大多数普通的mmap
调用(例如,由malloc
完成的调用)就会出局。
Of course, you should mmap
at some time before the first malloc
(which would probably call mmap
or sbrk
); 当然,您应该在第一个malloc
之前的某个时间进行 mmap
(可能会调用mmap
或sbrk
); and you should take care of the existing memory segments (perhaps you can get them by parsing /proc/self/maps
), because you need to avoid them in your mmap
MAP_FIXED|MAP_NORESERVE
. 并且应该注意现有的内存段(也许可以通过解析/proc/self/maps
来获取它们),因为需要在mmap
MAP_FIXED|MAP_NORESERVE
避免使用它们。
And you could also define your own malloc
. 您还可以定义自己的malloc
。 Perhaps you could mmap
with MAP_NORESERVE
a huge region (eg a terabyte), and have your own malloc
using only address inside (by mmap
-ing again there). 也许你可以mmap
与MAP_NORESERVE
一个巨大的区域(如TB级),并有自己malloc
使用只能解决内部(由mmap
-ing再次出现)。
I think you are trying to solve the wrong problem. 我认为您正在尝试解决错误的问题。 Doing what I suggest could be tricky... I see no valid reason to avoid addresses in the first 4 Gbytes. 执行我建议的操作可能会很棘手...我没有任何合理的原因来避免前4 GB中的地址。
BTW, a good tool to find memory leaks on Linux is valgrind . 顺便说一句, valgrind是查找Linux上内存泄漏的好工具。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.