2013-02-09 68 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)