2014-10-17 97 views
3

我使用mmap函數重新編碼malloc 。我正在使用最適合的算法,並且能夠在一個頁面中分配和解除分配。當我想分配小於頁面的大小時,我的malloc函數運行良好。重新編碼malloc和頁面大小

但我不明白我應該如何處理大於頁面大小的分配

回答

4

默認的libc malloc實現已經使用mmapMAP_ANONYMOUS分配大的單個內存分配。

爲了證明,這個編譯:

#include <stdio.h> 
#include <stdlib.h> 

int 
main (int argc, char **argv) 
{ 
    void *i = malloc (100 * 1024 * 1024); 
    exit (0); 
} 

然後strace下運行它:

$ strace ./x 2>&1 

execve("./x", ["./x"], [/* 21 vars */]) = 0 
brk(0)         = 0x135d000 
access("/etc/ld.so.nohwcap", F_OK)  = -1 ENOENT (No such file or directory) 
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7ad0fbb000 
access("/etc/ld.so.preload", R_OK)  = -1 ENOENT (No such file or directory) 
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 
fstat(3, {st_mode=S_IFREG|0644, st_size=105169, ...}) = 0 
mmap(NULL, 105169, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7ad0fa1000 
close(3)        = 0 
access("/etc/ld.so.nohwcap", F_OK)  = -1 ENOENT (No such file or directory) 
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\200\30\2\0\0\0\0\0"..., 832) = 832 
fstat(3, {st_mode=S_IFREG|0755, st_size=1811128, ...}) = 0 
mmap(NULL, 3925176, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f7ad09dc000 
mprotect(0x7f7ad0b91000, 2093056, PROT_NONE) = 0 
mmap(0x7f7ad0d90000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b4000) = 0x7f7ad0d90000 
mmap(0x7f7ad0d96000, 17592, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f7ad0d96000 
close(3)        = 0 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7ad0fa0000 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7ad0f9f000 
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7ad0f9e000 
arch_prctl(ARCH_SET_FS, 0x7f7ad0f9f700) = 0 
mprotect(0x7f7ad0d90000, 16384, PROT_READ) = 0 
mprotect(0x600000, 4096, PROT_READ)  = 0 
mprotect(0x7f7ad0fbd000, 4096, PROT_READ) = 0 
munmap(0x7f7ad0fa1000, 105169)   = 0 
mmap(NULL, 104861696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7aca5db000 
exit_group(0)       = ? 

這條線......

mmap(NULL, 104861696, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7aca5db000 

...是的分配大塊。

這就是你的問題的答案。您分配一個大尺寸和MAP_PRIVATE|MAP_ANONYMOUS

從手冊頁malloc

通常,malloc()從堆中分配內存,並根據需要調整大小 堆,使用sbrk(2)。當分配大於MMAP_THRESHOLD字節的存儲塊的塊 時,glibc malloc() 實現使用mmap(2)分配存儲器作爲專用匿名映射 。 MMAP_THRESHOLD默認爲128 kB,但使用mallopt(3)可調節爲 。使用mmap(2)執行的分配是 ,不受RLIMIT_DATA資源限制的影響(請參閱getrlimit(2))。

而且從手冊頁mallopt

M_MMAP_THRESHOLD

當分配請求大於給定值不能由現有的空閒塊來滿足時,該存儲器是保證與獲得mmap()的。較小的請求可能分配給mmap()sbrk()mmap() - 分配的內存可以在釋放時立即返回到操作系統,但對於分配爲sbrk()的所有內存不是這樣;然而,由mmap()分配的內存以及後來釋放的內存既不被加入也不被重用,因此開銷更大。默認值:128 * 1024。

M_MMAP_MAX

給定值設定的允許處於使用在給定時間(即使該分配請求的大小超過M_MMAP_THRESHOLD參數的值)mmap() -allocated塊的最大數量。這對於mmap()實施規模不佳的系統很有用。值爲0將禁用mmap()。默認值:65536

如果調M_MMAP_TRESHOLD下降到零(我不知道它是否會工作到這一步),我猜每個分配將要通過mmap完成,無需您更改多個代碼行。但無論如何,你的問題的答案是mmap與上述類似的參數。

請注意,可能不希望有太多的個人mmap'd區域,在這種情況下,您將希望在單個區域或多個區域內分配。在不改變地址的情況下增長mmap地區可能會很困難,並且這可能會導致在分配分散時返回操作系統的內存比較困難。