最小限の実行可能な例
brk()システムコールは何をしますか?
ヒープと呼ばれる連続したメモリのチャンクへの読み書きをカーネルに要求します。
質問しないと、segfaultする可能性があります。
なしbrk
:
#define _GNU_SOURCE
#include <unistd.h>
int main(void) {
/* Get the first address beyond the end of the heap. */
void *b = sbrk(0);
int *p = (int *)b;
/* May segfault because it is outside of the heap. */
*p = 1;
return 0;
}
とbrk
:
#define _GNU_SOURCE
#include <assert.h>
#include <unistd.h>
int main(void) {
void *b = sbrk(0);
int *p = (int *)b;
/* Move it 2 ints forward */
brk(p + 2);
/* Use the ints. */
*p = 1;
*(p + 1) = 2;
assert(*p == 1);
assert(*(p + 1) == 2);
/* Deallocate back. */
brk(b);
return 0;
}
GitHubアップストリーム。
上記は、がなくても新しいページに到達せず、segfaultにもならないbrk
可能性があるため、16MiBを割り当て、segfaultが発生しない可能性が非常に高いバージョンを次に示しbrk
ます。
#define _GNU_SOURCE
#include <assert.h>
#include <unistd.h>
int main(void) {
void *b;
char *p, *end;
b = sbrk(0);
p = (char *)b;
end = p + 0x1000000;
brk(end);
while (p < end) {
*(p++) = 1;
}
brk(b);
return 0;
}
Ubuntu 18.04でテスト済み。
仮想アドレス空間の視覚化
前brk
:
+------+ <-- Heap Start == Heap End
後brk(p + 2)
:
+------+ <-- Heap Start + 2 * sizof(int) == Heap End
| |
| You can now write your ints
| in this memory area.
| |
+------+ <-- Heap Start
後brk(b)
:
+------+ <-- Heap Start == Heap End
アドレススペースをよりよく理解するには、ページングに慣れる必要があります。x86ページングはどのように機能しますか?。
brk
との両方が必要なのはなぜsbrk
ですか?
brk
もちろんsbrk
+オフセット計算で実装することもできますが、どちらも便宜上存在しています。
バックエンドでは、Linuxカーネルv5.0には、brk
両方を実装するために使用される単一のシステムコールがあります:https : //github.com/torvalds/linux/blob/v5.0/arch/x86/entry/syscalls/syscall_64。 tbl#L23
12 common brk __x64_sys_brk
あるbrk
POSIXは?
brk
以前はPOSIXでしたが、POSIX 2001で削除されたため_GNU_SOURCE
、glibcラッパーにアクセスする必要があります。
削除の原因mmap
は、はじめにである可能性があります。これは、複数の範囲を割り当てることができるスーパーセットであり、割り当てオプションを増やすことができます。
brk
代わりに、malloc
またはmmap
今日使用する必要がある有効なケースはないと思います。
brk
対 malloc
brk
実装の古い可能性の1つmalloc
です。
mmap
は、おそらくすべてのPOSIXシステムが実装に現在使用している、より厳密で強力な新しいメカニズムmalloc
です。次に、最小限の実行可能なmmap
メモリ割り当ての例を示します。
混合brk
してmalloc できますか?
あなたmalloc
がで実装されている場合、単一の範囲のメモリしか管理しbrk
ないので、どうすればそれが爆発することがないのか私にはわかりませんbrk
。
しかし、glibcのドキュメントでそれについて何も見つけることができませんでした。例:
mmap
がに使われている可能性が高いので、物事はおそらくそこで機能するでしょうmalloc
。
以下も参照してください。
より詳しい情報
内部的には、カーネルはプロセスがそれだけのメモリを持つことができるかどうかを決定し、その使用のためにメモリページを割り当てます。
これは、スタックとヒープの比較方法を説明しています。x86アセンブリのレジスタで使用されるプッシュ/ポップ命令の機能は何ですか?