关于brk/sbrk的不安全/遗留之处是什么? [英] What's unsafe/legacy about brk/sbrk?

查看:102
本文介绍了关于brk/sbrk的不安全/遗留之处是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在很多地方(音乐邮件列表,macOS论坛等)都听说过brk()sbrk()是不安全的.这些地方中的许多要么根本不给出解释,要么给出非常模糊的解释.例如,链接指出这些功能从根本上说是损坏",并继续说mallocsbrk子系统完全损坏,它们破坏了堆,等等.

I've heard in a lot of places (musl mailing list, macOS forums, etc.) that brk() and sbrk() are unsafe. Many of these places either don't give explanations at all, or give very vague explanations. For example, this link states that "these functions are fundamentally broken", and goes on to say that the malloc and sbrk subsystems are utterly broken, that they ruin the heap, et al.

我的问题是:为什么会这样?如果使用malloc来分配sbrk足够大的内存块以平息或大大减少对进一步分配的需求,则sbrkbrk不应绝对安全地使用?

My question is: Why is this so? If malloc is used in such a way that it allocates a block of memory with sbrk large enough to quell or substantially decrease the need for further allocations, then shouldn't sbrk and brk be perfectly safe to use?

这是我的sbrkbrk的实现:

sbrk:

#include <unistd.h>
#include <stddef.h>

void *sbrk(intptr_t inc)
{
        intptr_t curbrk = syscall(SYS_brk, NULL);

        if( inc == 0 ) goto ret;

        if( curbrk < 0 ) return (void *)-1;

        curbrk((void *)(curbrk+inc));
ret:
        return (void *)curbrk;
}

brk:

#include <unistd.h>

intptr_t brk(void *ptr)
{
        if( (void *)syscall(SYS_brk, ptr) != ptr )
                return -1;
        else
                return 0;
}

推荐答案

现实高度依赖于实现,但以下是一些要素:

The reality highly depends on the implementation but here are some elements:

brk/sbrk来允许进程从系统请求更多的内存,并在单个连续的段中释放它.这样,它们被许多mallocfree实现使用.问题在于,当它返回一个唯一的段时,由于(同一进程的)多个模块直接使用它,会出错.由于竞争条件,在多线程进程中情况变得更糟.假设有2个线程想要添加新的内存.他们将使用sbrk(0)查看当前的最高地址,看到相同的地址,并使用brksbrk请求新的内存,并且由于竞争条件,它们都将使用相同的内存.

brk/sbrk were invented to allow a process to request more memory from the system, and release it in a single contiguous segment. As such, they were used by many malloc and free implementations. The problem was that, as it returned a unique segment, things would go wrong as multiple modules (of the same process) use it directly. It became even worse in a multi-threaded process because of race conditions. Suppose 2 threads want to add new memory. They will look at the current top address with sbrk(0), see the same address, request new memory with either brk or sbrk, and because of the race condition, will both use the same memory.

即使在单线程进程中,某些mallocfree实现也假定仅允许它们使用低级s/brk接口,并且任何其他代码也应使用它们.在这种情况下,如果内部保留的中断片段的图像不再是假定值,那么事情将会出错.他们应该猜测该段的某些部分被保留"用于其他用途,可能会破坏释放任何内存的能力.

Even in a single threaded process, some malloc and free implementations assume that they only are allowed to use the low level s/brk interface, and that any other code should use them. In that case things will go wrong if the image of the break segment that they internally maintain is no longer the assumed value. They should have to guess that some parts of the segment are "reserved" for other uses, possibly breaking the ability to release any memory.

因此,用户代码绝对不能直接使用brk/sbrk,而只能依靠malloc/free.当且仅当您正在编写包含malloc/realloc/calloc/free的标准库的实现时,才可以安全地使用brk/sbrk

For that reason, user code should never directly use brk/sbrk and only rely on malloc/free. If, and only if, you are writing an implementation of the standard library including malloc/realloc/calloc/free, you can safely use brk/sbrk

在现代系统上,mmap可以更好地使用虚拟内存管理.您可以根据需要使用任意数量的动态内存段,而无需在它们之间进行交互.因此,在现代系统上,除非您特别需要使用brk/sbrk进行内存分配,否则应使用mmap.

On modern system, mmap can make a much nicer usage of virtual memory management. You can use as many dynamic memory segments as you need with no interaction between them. So, on a modern system, unless you have a specific need for memory allocation using brk/sbrk, you should use mmap.

brksbrk的FreeBSD参考说明如下:

The FreeBSD reference for brk and sbrk states this:

brk()和sbrk()函数是以前的旧接口 现代虚拟内存管理的出现.

The brk() and sbrk() functions are legacy interfaces from before the advent of modern virtual memory management.

及更高版本:

错误: 将brk()或sbrk()与malloc(3),free(3)或类似函数混合使用 导致程序无法移植.

BUGS: Mixing brk() or sbrk() with malloc(3), free(3), or similar functions will result in non-portable program behavior.

这篇关于关于brk/sbrk的不安全/遗留之处是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆