2013-02-09 66 views
0

我需要找到一种方法来使用mmap而不是malloc。这怎么可能? (我不使用libc只有系统调用)并且是brk()是可能的。我用sbrk(),但实现了它不是系统调用...(x86内联汇编)mmap替代malloc

我一直在环顾四周,看到这个:How to use mmap to allocate a memory in heap?但它没有帮助我,因为我有一个段错误。

基本上,我想要创建3块存储字符的内存块。

说,

char * x = malloc(1000); 
char * y = malloc(2000); 
char * z = malloc(3000); 

这怎么可能用MMAP以及如何与munmap后释放它?

+0

http://www.kernel.org/doc/man-pages/online/pages/man2/sbrk。 2.html是系统调用,但不推荐使用。 – 2013-02-09 09:25:25

+1

如果合适,glibc'malloc'使用'mmap'(例如,如果要分配的字节数量超过某个阈值) – 2013-02-09 09:25:50

+1

取自malloc手册页:通常,malloc()从堆中分配内存并调整根据需要使用sbrk(2)来确定堆的大小。当分配大于MMAP_THRESHOLD字节的内存块时,glibc malloc()实现使用mmap(2)将内存分配为专用匿名映射。 MAP_THRESHOLD默认为128 kB,但可以使用mallopt(3)进行调整。使用mmap(2)执行的分配不受RLIMIT_DATA资源限制的影响(请参阅getrlimit(2))。 – 2013-02-09 09:27:18

回答

9

您是否仔细阅读过mmap(2)手册页?我建议多读几遍。

请注意,您只能要求内核[通过mmap etc ...]来管理内存对齐和页面大小sysconf(_SC_PAGE_SIZE),通常是4096字节(我假设在我的答案中)的多倍。

那么你可以做:

size_t page_size = sysconf(_SC_PAGE_SIZE); 
    assert (page_size == 4096); // otherwise this code is wrong 

    // 1000 bytes fit into 1*4096 
    char *x = mmap (NULL, page_size, PROT_READ|PROT_WRITE, 
        MAP_ANONYMOUS, -1, (off_t)0); 
    if (x == MMAP_FAILED) perror("mmap x"), exit (EXIT_FAILURE); 

    // 2000 bytes fit into 1*4096 
    char *y = mmap (NULL, page_size, PROT_READ|PROT_WRITE, 
        MAP_ANONYMOUS, -1, (off_t)0); 
    if (y == MMAP_FAILED) perror("mmap y"), exit (EXIT_FAILURE); 

后释放内存,使用

if (munmap(x, page_size)) 
    perror("munmap x"), exit(EXIT_FAILURE); 

如果你想分配5K字节,你需要两个网页(因为5Kbytes < 2 * 4096和5Kbytes> 1 * 4096)即mmap(NULL, 2*page_size, ...

其实,你所有的x,y,z只需要8000个字节,可以放入两个而不是三个页面......但是那么你只能把munmap那个内存放在一起。

请注意,mmap是一个系统调用,可能相当昂贵。 malloc的实现注意避免过于频繁地调用它,这就是为什么他们管理以前的free -d区域以便稍后重新使用它们(在进一步的malloc -s中),而没有任何系统调用。实际上,大多数malloc实现管理不同的大分配(例如超过兆字节),这通常是mmap -ed在mallocmunmap -ed在free时间....您可以研究一些malloc的源代码。来自MUSL Libc的那个可能比Glibc malloc更容易阅读。

顺便说一句,文件/proc/1234/maps显示了pid 1234的进程的内存映射。在终端中也尝试cat /proc/self/maps,它显示了那个进程的内存映射。

+0

谢谢,这有帮助很多! – Kalon 2013-02-10 01:20:50

+0

应该是“sysconf(_SC_PAGESIZE)”吗? – Ant6n 2014-10-18 19:50:35

2

您可以拨打mmap,使在86 ASM匿名映射的东西,如:

mov eax, 192 ; mmap 
    xor ebx, ebx ; addr = NULL 
    mov ecx, 4096 ; len = 4096 
    mov edx, $7  ; prot = PROT_READ|PROT_WRITE|PROT_EXEC 
    mov esi, $22 ; flags = MAP_PRIVATE|MAP_ANONYMOUS 
    mov edi, -1  ; fd  = -1 (Ignored for MAP_ANONYMOUS) 
    xor ebp, ebp ; offset = 0 (4096*0) (Ignored for MAP_ANONYMOUS) 
    int $80   ; make call (There are other ways to do this too)