【发布时间】:2014-08-21 08:44:25
【问题描述】:
函数page_allocate 工作。它确实将地址返回到具有指定对齐方式的映射页面。但是,使用 64k 和 1024k 的连续呼叫永远不会连续。为什么?
- ./mmap 0x00001000 //4k
- ./mmap 0x00002000 //8k
- ./mmap 0x00004000 //16k
- ./mmap 0x00008000 //32k
- ./mmap 0x00010000 //64k 坏?在连续分配中无法获得连续范围
- ./mmap 0x00020000 //128k
- ./mmap 0x00040000 //256k
- ./mmap 0x00080000 //512k
- ./mmap 0x00100000 //1024k 错误?
- ./mmap 0x00200000 //2048k
- ./mmap 0x00400000 //4096k
- ./mmap 0x00800000 //8192k
- ./mmap 0x01000000 //16384k
- ./mmap 0x10000000 //256Mb
- ./mmap 0x100000000 //4096mb
这里包含一个示例程序。使用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没有有返回连续的地址。这完全取决于第一个地址在哪里,以及是否有其他东西在路上。它可能会在不同的区域发出不同大小的请求。