簡體   English   中英

關於brk / sbrk有什么不安全/遺產?

[英]What's unsafe/legacy about brk/sbrk?

我聽說很多地方(musl郵件列表,macOS論壇等) brk()sbrk()都不安全。 其中許多地方要么根本不作解釋,要么給出非常含糊的解釋。 例如, 這個鏈接指出“這些函數從根本上被打破”,並繼續說mallocsbrk子系統完全被破壞,它們毀了堆,等等。

我的問題是:為什么會這樣? 如果malloc以這樣一種方式使用,它分配一塊內存塊,其sbrk足夠大,可以平息或大大減少進一步分配的需要,那么sbrkbrk應該完全安全使用?

以下是我對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;
}

現實在很大程度上取決於實施,但這里有一些要素:

不安全

發明了brk / sbrk ,允許進程從系統請求更多內存,並在單個連續段中釋放它。 因此,它們被許多mallocfree實現使用。 問題在於,當它返回一個獨特的段時,由於多個模塊(同一個過程)直接使用它,因此會出錯。 由於競爭條件,它在多線程過程中變得更糟。 假設2個線程想要添加新內存。 他們將使用sbrk(0)查看當前的頂部地址,查看相同的地址,使用brksbrk請求新內存,並且由於競爭條件,兩者都將使用相同的內存。

即使在單線程進程中,一些mallocfree實現也假設它們只允許使用低級s/brk接口,並且任何其他代碼都應該使用它們。 在這種情況下,如果他們內部維護的中斷段的圖像不再是假定值,則會出錯。 他們應該猜測該段的某些部分是“保留”用於其他用途,可能會破壞釋放任何內存的能力。

因此,用戶代碼永遠不應該直接使用brk / sbrk而只能依賴malloc / free 如果且僅當您正在編寫包含malloc / realloc / calloc / free的標准庫的實現時,您可以安全地使用brk / sbrk

遺產

在現代系統中, mmap可以更好地利用虛擬內存管理。 您可以根據需要使用盡可能多的動態內存段,而不需要它們之間的交互。 因此,在現代系統中,除非您特別需要使用brk / sbrk進行內存分配,否則應使用mmap

可移植性

brksbrk的FreeBSD參考說明了這一點:

brk()和sbrk()函數是現代虛擬內存管理出現之前的傳統接口。

然后:

BUGS:將brk()或sbrk()與malloc(3),free(3)或類似函數混合將導致不可移植的程序行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM