我使用mmap函數重新編碼malloc 。我正在使用最適合的算法,並且能夠在一個頁面中分配和解除分配。當我想分配小於頁面的大小時,我的malloc函數運行良好。重新編碼malloc和頁面大小
但我不明白我應該如何處理大於頁面大小的分配?
我使用mmap函數重新編碼malloc 。我正在使用最適合的算法,並且能夠在一個頁面中分配和解除分配。當我想分配小於頁面的大小時,我的malloc函數運行良好。重新編碼malloc和頁面大小
但我不明白我應該如何處理大於頁面大小的分配?
默認的libc malloc實現已經使用mmap
和MAP_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
字節的存儲塊的塊 時,glibcmalloc()
實現使用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
地區可能會很困難,並且這可能會導致在分配分散時返回操作系統的內存比較困難。