[英]Consecutive mmap call never return contiguous address
函數page_allocate
起作用。 它確實將地址返回到具有指定對齊方式的映射頁面。 但是,使用64k和1024k的連續調用永遠不會是連續的。 為什么?
這里包括一個示例程序。 使用gcc -Wall -g mmap.c -o mmap
進行編譯。
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#define _GNU_SOURCE /* MAP_ANONYMOUS */
#include <sys/mman.h>
#include <unistd.h> /* sysconf */
static size_t sys_page_size = 0;
void
page_init(void)
{
int sc;
if(!sys_page_size)
{
sc = sysconf(_SC_PAGESIZE);
if(sc == -1)
{
sys_page_size = 0x0000000000001000; /* Default to 4Kb */
}
else
{
sys_page_size = sc;
}
}
}
void *
page_allocate(size_t request,
size_t alignment)
{
size_t size;
size_t slop;
void *addr;
/* Round up to page size multiple.
*/
request = (request + (sys_page_size - 1)) & ~(sys_page_size -1);
alignment = (alignment + (sys_page_size - 1)) & ~(sys_page_size -1);
size = request + alignment;
/* Maybe we get lucky.
*/
addr = mmap(NULL,
request,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS,
-1,
0);
if(!((uintptr_t)addr & (alignment - 1)))
{
return addr;
}
munmap(addr, request);
addr = mmap(NULL,
size,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS,
-1,
0);
slop = (uintptr_t)addr & (request - 1);
#define POINTER_OFFSET(addr, offset) ((void *)((uintptr_t)(addr) + (offset)))
if(slop)
{
munmap(addr, request - slop);
munmap(POINTER_OFFSET(addr, size - slop), slop);
addr = POINTER_OFFSET(addr, request - slop);
}
else
{
munmap(POINTER_OFFSET(addr, request), request);
}
return addr;
}
int
main(int argc,
char **argv)
{
size_t size;
void *cmp = NULL;
void *ptr[16];
int i;
page_init();
if(argc == 2)
{
size = strtol(argv[1], NULL, 16);
}
else
{
size = 0x00001000;
}
for(i = 0;
i < 16;
i ++)
{
ptr[i] = page_allocate(size, size);
}
for(i = 0;
i < 16;
i ++)
{
printf("%2i: %p-%p %s\n",
i,
ptr[i],
(void *)((uintptr_t)ptr[i] + size - 1),
(llabs(ptr[i] - cmp) == size) ? "contiguous" : "");
cmp = ptr[i];
}
return 1;
}
您永遠不要期望mmap
自己提供連續的地址,但是您可以嘗試通過請求一個地址來獲取它們,只要地址范圍是空閑的,該地址就可以使新的映射成為連續的,並且省略MAP_FIXED
以便所請求的地址僅是用作提示(使用MAP_FIXED
,它將替換已經存在的內容,這絕對不是您想要的)。
我懷疑您看到mmap
為某些調用(但不是全部)返回連續映射的原因是內核試圖平衡使新VM區域的成本與希望地址不可預測(ASLR)的成本之間的平衡。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.