手册页(部分:C库brk(2)
/内核 ABI 差异)描述了 glibc 包装器是如何在 Linux 的系统调用之上实现的,它在成功时返回新的 brk,或者在失败时返回旧的 brk。
据我了解,当前中断之外的内存未映射。当前中断以下的地址是数据段的一部分(在数据+bss+堆的意义上)。文档不清楚中断是否必须与页面对齐。(即您可以使用 sbrk(64),还是只能使用 sbrk(4096)?)
请参阅:brk() 系统调用是做什么的? 该问题的答案有一个使用 sbrk 替换 malloc 为 code-golf 的示例。所以是的,旧的休息是返回的地址。显然你可以sbrk
增加任何你想要的,而不仅仅是页面。
您是编写内存分配器的人。 sbrk
只是让您从操作系统中获得更多,mmap(MAP_ANONYMOUS)
但不太灵活。 它不能帮助您跟踪空闲块,因此您可以将它们用于将来的分配,而不是总是从操作系统获得更多。
回馈您获得的内存的方法是使用否定参数sbrk
进行调用。sbrk
显然这需要后进先出的使用模式,这就是为什么 glibc 的 malloc 仅sbrk
用于小分配(释放时可以放在 free-list 上,以供将来的 malloc 分发)。大分配最好立即返回给操作系统,而不是保持映射,因此 glibc 的 mallocmmap
用于这些。
永远不要调用free(3)
您没有从中获得的内存malloc(3)
(或相关函数,例如strdup(3)
,在文档中说您可以并且应该free(3)
使用内存。) IDK 如果您munmap
在程序中断下方的内存页面上调用会发生什么。可能它会起作用,但是如果中断减少到那里,您可能会保留数据段,这可能会导致问题。
后来意识到这不是你要问的:
获取当前 brk 的最简单方法是简单地使用increment = 0
.
这是 glibcmalloc(3)
在内部所做的:
$ strace -e brk ls 2>&1 | m
brk(0) = 0x650000
brk(0) = 0x650000
brk(0x671000) = 0x671000
brk 手册页提到end(3)
. 显然有一些全局变量位于文本、数据和 bss 段的末尾。但是,&end
程序中断只是“某处附近”,这就是为什么 malloc 仍然必须调用 sbrk(0) 才能获得初始中断。