我可以在哪里详细了解sbrk()
?
它是如何起作用的?
在什么情况下我想使用sbrk()
而不是繁琐的malloc()
和new()
?
顺便问一下,sbrk()
的扩展是什么?
答案 0 :(得分:8)
查看the specification for brk/sbrk。
该调用基本上要求操作系统通过将先前的“中断值”增加一定量来为应用程序分配更多内存。这个数量(第一个参数)是你的应用程序获得的额外内存量。
大多数基本的malloc实现都是基于sbrk系统调用来获取它们分裂和跟踪的内存块。 mmap函数通常被认为是一个更好的选择(这就是为什么像dlmalloc这样的malloc都支持#ifdef)。
至于“它如何运作”,其最简单级别的sbrk看起来像这样:
uintptr_t current_break; // Some global variable for your application.
// This would probably be properly tracked by the OS for the process
void *sbrk(intptr_t incr)
{
uintptr_t old_break = current_break;
current_break += incr;
return (void*) old_break;
}
现代操作系统可以做得更多,例如将地图页面放入地址空间,并为每个分配的内存块添加跟踪信息。
答案 1 :(得分:4)
sbrk已经过时了,现在你使用mmap将一些页面映射到/ dev / zero。它肯定不是你用的东西而不是malloc和朋友,它更像是一种实现它的方式。当然,它只存在于基于posix的操作系统上,它们关注与古代代码的向后兼容性。
如果您发现Malloc和New过于繁琐,您应该考虑垃圾收集......但要注意,这可能会带来性能成本,因此您需要了解自己在做什么。
答案 2 :(得分:1)
您永远不想使用sbrk
代替malloc
或free
。它是不可移植的,通常仅由标准C库的实现者使用,或者在不可用的情况下使用。它在man page:
说明
brk()设置结束 数据段到指定的值 end_data_segment,当该值为 合理,系统确实有 足够的内存和过程没有 超过其最大数据大小(见 的setrlimit(2))。
sbrk()递增程序的数据 空间增量字节。 sbrk()不是 系统调用,它只是一个C库 包装。用s调用sbrk() 增量0可用于查找 程序中断的当前位置。
返回值
成功时,brk()返回 零,sbrk()返回一个指针 新区域的开始。出错, 返回-1,并将errno设置为ENOMEM。
最后,malloc
和free
并不麻烦 - 它们是在C中分配和释放内存的标准方法。即使您想要实现自己的内存分配器,最好只使用{ {1}}和malloc
作为基础 - 一种常见的方法是使用free
一次分配一个大块并从中提供内存分配(这是子分配器或池通常实现的)
重新命名malloc
(或其堂兄sbrk
)的起源,它可能与堆的末端被称为“中断”的指针标记有关”。堆在BSS段之后立即开始,并且通常朝向堆栈增长。
答案 3 :(得分:1)
你已经标记了这个C ++,为什么你会使用'繁琐的'malloc()而不是new?我不确定在任何情况下malloc的繁琐程度如何;内心可能如此,但你为什么要关心?如果您确实关心(例如,出于确定性的原因),您可以分配一个大型池并为该池实现自己的分配器。当然,在C ++中,您可以重载新运算符来执行此操作。
sbrk用于将C库粘合到底层系统的OS内存管理中。因此,请使用OS调用而不是使用sbrk()。至于它是如何工作的,这取决于系统。例如,如果您正在使用Newlib C库(通常在'裸机'嵌入式系统上使用GNU编译器),则必须implement sbrk yourself,因此在这些情况下它的工作原理取决于您它实现了扩展堆或失败所需的行为。
正如您从链接中看到的那样,它没有做太多工作并且直接使用非常很麻烦 - 您可能最终将它包装在malloc和new提供的所有功能中无论如何。
答案 4 :(得分:0)
这取决于malloc是“繁琐”的意思。 sbrk通常不再直接使用,除非你实现自己的内存分配器:IE,运算符覆盖“new”。即便如此,我也可以使用malloc给我最初的记忆。
如果您想了解如何在sbrk()之上实现malloc(),请查看http://web.ics.purdue.edu/~cs354/labs/lab6/,这是一个练习。
在现代系统上,你不应该触摸这个界面。由于你正在调用malloc和新的繁琐,我怀疑你没有必要的经验来安全和正确地使用sbrk代码。