在Unix中,malloc()和sbrk()如何工作?

15

我是UNIX的新手,正在学习一些UNIX系统调用,例如brk()sbrk()等...

昨天我读到了malloc()函数,并且有点困惑!有人能告诉我为什么malloc()会减少程序必须执行的sbrk()系统调用次数吗?

还有一个问题,brk(0)sbrk(0)malloc(0)返回相同的值吗?


2
由于brk返回一个int值,而sbrk返回一个void指针,所以我认为不行。 - Mithrandir
4个回答

47
系统调用的处理开销很高,因为系统调用会带来额外的开销:需要切换到内核模式。通过发出“陷阱”或中断,系统调用进入内核。它是向内核请求服务的调用,因为它在内核地址空间中执行,所以它需要高开销的切换到内核(然后再切回用户态)。
这就是为什么malloc减少了对sbrk()brk()的调用次数。它通过请求比您请求的内存更多的内存来实现,这样每次需要更多内存时就不必发出系统调用了。 brk()sbrk()是不同的。 brk用于将数据段的结尾设置为指定值。它表示“将我的数据段的结尾设置为此地址”。当然,您指定的地址必须是合理的,操作系统必须有足够的内存,而且您不能使其指向会超过进程最大数据大小的地方。因此,brk(0)无效,因为您将尝试将数据段的结尾设置为地址0,这是不合理的。
另一方面,sbrk按您指定的数量递增数据段的大小,并返回先前的断点值的指针。使用0调用sbrk是有效的;这是获得当前数据段断点地址的一种方式。 malloc不是系统调用,它是一个使用sbrk管理内存的C库函数。根据手册,malloc(0)是有效的,但没有太多用途:
如果size为0,则malloc()返回NULL,或者可以稍后成功传递给free()的唯一指针值。

因此,brk(0)sbrk(0)malloc(0)并不相等:第一个是无效的,第二个用于获取程序断点的地址,而最后一个则没有用处。

请记住,在整个程序中不应该同时使用mallocbrksbrk。如果你交替调用mallocbrk,非常奇怪的事情可能会发生,因为malloc假定它完全控制了brksbrk


13
为什么使用malloc()可以减少程序必须执行的sbrk()系统调用次数?
例如,如果您调用malloc()请求10字节内存,则实现可能使用sbrk(或其他系统调用,如mmap)从操作系统请求4K字节。然后,当您下次调用malloc()请求另外10字节时,它不必发出系统调用;它可能只需返回上次4K系统调用分配的一些内存即可。

1

sbrk() 函数通过指定的字节数增加程序数据段分配。

malloc(4096); // sbrk += 4096 Bytes
free();       // freeing memory will not bring down the sbrk by 4096 Bytes  
malloc(4096); // malloc'ing again will not increase the sbrk and it will use 
                 the existing space which not result in sbrk() call.  

1

malloc()函数用于调用sbrk系统调用,以在进程期间动态创建内存。

malloc()函数已经分配在stdlib.h头文件中,因此根据所需的函数,使用库函数递归地调用malloc函数。

借助sbrk,我们需要显式声明一些内容来调用系统调用。

根据函数或系统调用中给定的大小,它将返回变量并存储。


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