为了一个研究项目,我需要使用mmap()
和munmap()
重新实现malloc()
和free()
的编码。
我在最新版本的Ubuntu上运行。为了进行测试,我使用/usr/bin/time
命令的time -v
选项,该选项向我显示有关我的程序包括内存的大量信息。以下是一些示例:
因此,我们可以看到次要页面错误
,它对应于根据我们的使用而变化的回收页面数量,但特别是如果我们在malloc()
之后使用free()
,则回收页面的数量将返回到其初始数量,这在我的重新实现中不是这种情况:
以下是我代码的一些部分,以便可视化我所做的事情。
在我的malloc()
中:
static t_page *__alloc_page(size_t size)
{
struct rlimit limit;
t_page *page;
getrlimit(RLIMIT_AS, &limit);
if (size > limit.rlim_max)
return (NULL);
page = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (page == MAP_FAILED)
return (NULL);
ft_bzero(page, sizeof(t_page));
page->size = size;
page->used_size = sizeof(t_page);
return (page);
}
在我的
free()
函数里:static void __free_page(t_page *page)
{
t_binding *binder = __get_binder(page);
binder->count--;
if (binder->pages == page)
binder->pages = page->next;
if (page->prev != NULL)
page->prev->next = page->next;
if (page->next != NULL)
page->next->prev = page->prev;
if (munmap(page, page->size) == -1)
ft_putstr("free(): munmap error\n");
}
关于我的大小信息,它总是getpagesize()
的倍数(N * getpagesize()
)。
这是我如何进行测试的
首先,我将文件malloc.c
、free.c
等编译成动态库(libmalloc.so
)。
然后,我使用以下主函数构建两个二进制文件。一个使用我的malloc,另一个使用libc。
clang main.c -o libc_malloc
clang main.c -D LIBMALLOC libmalloc.so -o my_malloc
#ifdef LIBMALLOC
# include "../includes/malloc.h"
#else
# include <stdlib.h>
#endif
int main(void)
{
int i;
char *addr;
i = 0;
while (i < 1024)
{
addr = (char*)malloc(1024);
addr[0] = 42;
free(addr);
i++;
}
return (0);
}
我还有一个脚本,可以让我使用名为run.sh
的动态库运行我的二进制文件:
#!/bin/sh
export LD_LIBRARY_PATH="."
export LD_PRELOAD="`pwd`/libmalloc.so"
$@
最后我用
time -v
运行了我的两个二进制文件,就像这样:/usr/bin/time -v ./libc_malloc
./run.sh /usr/bin/time -v ./my_malloc
如何以最简方式进行复现
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main(void)
{
int i;
char *addr;
i = 0;
#ifdef _MMAP_
printf("mmap\n");
#else
printf("malloc\n");
#endif
while (i < 1024)
{
#ifdef _MMAP_
addr = mmap(NULL, 4 * getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#else
addr = malloc(4 * getpagesize());
#endif
addr[0] = 42;
#ifdef _MMAP_
munmap(addr, 4 * getpagesize());
#else
free(addr);
#endif
i++;
}
return (0);
}
将上述主函数复制到一个文件中(main.c
)。
创建两个二进制文件如下:
clang main.c -o using_malloc
clang -D _MMAP_ main.c -o using_mmap
然后使用time -v
运行它们:
/usr/bin/time -v ./using_malloc
/usr/bin/time -v ./using_mmap
我尝试过的方法
在搜索互联网时,我发现了这篇文章,它与我的问题完全相同:
使用munmap时页面回收更高
但是提出的解决方案不起作用(而且我不能使用它)。
我也不能使用像posix_madvise()
或msync()
这样的函数...
我尝试了它们,看看它们是否能解决我的问题,但没有成功。
我还运行了别人的项目。他的工作得很好,而我们似乎在做同样的事情。
我错过了什么吗?
RSS
(常驻集大小)。请注意,映射/取消映射并不完全等同于RSS,因此如果没有使用posix_madvise/madvise/msync
,您将无法对进程的RSS进行如此多的控制。 - Craig Esteymalloc
和free
调用的是您的版本而不是标准库中的版本吗?要实现这一点可能需要付出一些努力。 - Nate Eldredgemain
函数也没有帮助,因为它们似乎实际上并没有测量任何东西。 - Nate Eldredge