【发布时间】:2012-01-17 10:35:26
【问题描述】:
如果 malloc/free 在 libc 中作为库例程实现,那么它是在 sbrk 系统调用或 mmap 系统调用之上实现的,还是其他什么?
一般来说,sys/syscall.h中声明的函数是否包含目标机器中的所有系统调用?
【问题讨论】:
-
如果你有 libc 的源代码...
标签: c linux system-calls libc
如果 malloc/free 在 libc 中作为库例程实现,那么它是在 sbrk 系统调用或 mmap 系统调用之上实现的,还是其他什么?
一般来说,sys/syscall.h中声明的函数是否包含目标机器中的所有系统调用?
【问题讨论】:
标签: c linux system-calls libc
很多时候,malloc 和 free 使用较低级别的虚拟内存分配服务并一次分配多个页面(甚至是兆字节),使用 system calls,例如 mmap 和 munmap(可能还有 @ 987654324@)。通常malloc 更喜欢在相关时重用以前 freed 内存空间。大多数malloc 实现对“大”和“小”分配等使用各种不同的策略......
注意virtual address space 可以被限制,例如与setrlimit(2)。在 Linux 上使用 pmap(1) 和 proc(5) 以了解有关某些进程的虚拟地址空间的更多信息(例如,/proc/self/maps 用于您自己的一个或 /proc/1234/maps - 也是 pmap 1234 命令 - 用于 pid 1234 的进程)。
您可以查看您的 GNU libc 源代码,查看其他 C 标准库的源代码(例如 musl-libc),阅读有关 malloc implementations 的信息,选择一些 other ones 或实现您自己的,或者使用strace进行实验发现。
阅读syscalls man page(即syscalls(2))和文件<asm/unistd.h>以获取系统调用列表。
malloc
(我相信这可能是malloc的最快实现;但是它不是很有用;它符合标准,例如n1570或更好)
我坚信 C 标准对 malloc 和 free 非常模糊。我很确定以下功能尊重标准的文字(但不是精神):
/* politically incorrect, but very probably standard conforming */
void *malloc (size_t sz) { if (sz>0) errno = ENOMEM; return NULL; }
void free(void*ptr) { }
当然,您会相应地编码calloc 和realloc。
(顺便说一句,每个使用 malloc 的代码都应该测试它的失败,但有些 - 不正确 - 不要;malloc 可以在失败时返回 NULL,人们应该针对这种情况进行测试)
GNU libc 为您提供hooks 用于您自己的malloc 函数(您甚至可以通过它们透明地使用Boehm's Garbage Collector)。这些钩子可能会被弃用并且是非标准的。
如果使用 GNU libc,还请查看 mallinfo(3) 和 malloc_stat(3) 以及相关函数。
【讨论】:
malloc 和 free 可以更简单,例如 #define malloc(x) NULL 和 #define free(x) (void)1 :-) ISO 不需要设置 errno,这是 POSIX 的事情.您可能还想拦截calloc 和realloc。
malloc 可以只是一个宏吗?我认为它应该是一个函数(可分配给函数指针)
malloc 和 free 是标准 C 库函数,每个 C 实现都将实现它们。
C 标准只定义了这些函数的行为方式以及它们所期望的行为。它们将如何实现留给每个实现。
简而言之,它们是您使用的实现的实现细节。
(“实现”由编译器、链接器、运行时库以及可能的其他一些东西组成。)
【讨论】:
malloc 和 free 被实现为调用低级代码的库函数。如果操作系统碰巧提供的系统调用与 C 标准对 malloc 和 `free 所要求的行为完全匹配,那么它们可以作为系统调用来实现。但我不知道有任何操作系统可以做到这一点(甚至是 Unix,C 的诞生地)。
如果您使用不同的内存分配器,您还可以为 malloc 和 free 使用替代实现。例如,hoard memory allocator 有时用于提高多线程应用程序的性能。
【讨论】: