malloc/free是由libc提供的库例程还是系统调用(syscall)?

23

如果在libc中以库例程的形式实现malloc/free函数,那么它是基于sbrk系统调用还是mmap系统调用,还是其他什么方式实现的?

并且一般来说,sys/syscall.h中声明的函数是否包含目标机器上所有的系统调用?


7
如果你有libc的源代码就好了... - bk1e
3个回答

48

很多时候,mallocfree使用较低级别的虚拟内存分配服务,并一次性分配几个页面(甚至数兆字节),使用类似mmapmunmap(以及可能的sbrk)的系统调用。通常情况下,malloc更喜欢在相关时重复使用先前free的内存空间。大多数malloc实现使用不同的策略来处理“大”和“小”的分配等等...

注意虚拟地址空间可能会受到限制,例如使用setrlimit(2)。在Linux上,可以使用pmap(1)proc(5)来了解某些进程的虚拟地址空间(例如/proc/self/maps用于您自己的进程或/proc/1234/maps - 也可以使用pmap 1234命令 - 用于pid为1234的进程)。
您可以查看GNU libc源代码,查看其他C标准库的源代码(如musl-libc),阅读有关malloc实现的文章,选择一些其他的实现或者自己实现,并使用strace进行实验。
阅读syscalls man page(即syscalls(2))和文件<asm/unistd.h>以获取系统调用列表。

一个非常快的malloc

(我相信这可能是最快的malloc实现;但它并不是非常有用;它符合标准,例如n1570或更好)

我坚信C标准对于mallocfree非常模糊。我非常确定以下函数遵守标准的字面意思(但不是精神意义):

 /* politically incorrect, but very probably standard conforming */
 void *malloc (size_t sz) { if (sz>0) errno = ENOMEM; return NULL; }
 void free(void*ptr) { }

当然,你需要相应地编写callocrealloc的代码。

顺便提一下,每个使用malloc的代码都应该针对其失败进行测试,但有些人-不正确地-没有这样做;malloc在失败时可能返回NULL,人们应该针对这种情况进行测试。


GNU libc提供了钩子以供您自己的malloc函数使用(您甚至可以透明地通过它们使用Boehm's Garbage Collector)。这些钩子可能会被弃用并且不是标准的。

如果使用GNU libc,请还要查看mallinfo(3)malloc_stat(3)及相关函数。


4
实际上,mallocfree 可以更简单,类似于 #define malloc(x) NULL#define free(x) (void)1 :-) ISO 标准不要求设置 errno,这是 POSIX 的一件事。您可能还想拦截 callocrealloc - paxdiablo
3
你确定 malloc 可以只是一个宏吗?我认为它应该是一个函数(可分配给函数指针)。 - Basile Starynkevitch
1
好观点,我认为你是对的,我没有想到那个。你仍然可以放弃errno设置。 - paxdiablo

13

mallocfree是标准C库函数,每个C实现都需要实现它们。

C标准只定义了这些函数的行为和预期行为,如何实现它们则由每个实现自行决定。

简而言之,它们是您使用的实现的实现细节。

(一个“实现”包括编译器、链接器、运行时库以及可能还有其他一些东西。)


由平台的 C 库实现,而非编译器。 - u0b34a0f6ae
@kaizer.se:编译器可以自由地拥有自己的标准库(嘿!),但通常没有太大意义。 - dmckee --- ex-moderator kitten
2
@kaizer.se:这取决于编译器,编译器可以使用平台提供的标准库实现,也可以提供自己的相同实现。选择哪一个取决于编译器。这就是“实现细节”的含义。 - Alok Save
3
通常情况下,mallocfree被实现为库函数,调用底层代码。如果操作系统提供的系统调用恰好符合C标准对mallocfree的要求,则它们可以作为系统调用实现。但是我不知道任何一个这样做的操作系统(即使是C语言的发源地Unix)。 - Keith Thompson

3

如果您使用不同的内存分配器,还可以使用替代实现来替换mallocfree。例如,hoard内存分配器有时用于提高多线程应用程序的性能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接