malloc_state はアリーナを抽象化した構造体です。
さらに malloc_state のスタティックオブジェクトにしたものが main_arena です。
この main_arena は malloc() を使わなくても自動に割り当てされます。
empty.c.
1 int main(){
2 return 0;
3 }
empty.c の GDB デバッグ.
$ gcc empty.c -g
$ gdb ./a.out
(gdb) break main
(gdb) run
Breakpoint 1, main () at empty.c:2
2 return 0;
(gdb) info proc mappings
process 2792
Mapped address spaces:
Start Addr End Addr Size Offset objfile
0x555555554000 0x555555555000 0x1000 0x0 /home/komatsu/system_c_programming/mmap-book/arena/a.out
0x555555754000 0x555555755000 0x1000 0x0 /home/komatsu/system_c_programming/mmap-book/arena/a.out
0x555555755000 0x555555756000 0x1000 0x1000 /home/komatsu/system_c_programming/mmap-book/arena/a.out
0x7ffff75db000 0x7ffff75de000 0x3000 0x0 /lib/x86_64-linux-gnu/libdl-2.27.so
0x7ffff75de000 0x7ffff77dd000 0x1ff000 0x3000 /lib/x86_64-linux-gnu/libdl-2.27.so
0x7ffff77dd000 0x7ffff77de000 0x1000 0x2000 /lib/x86_64-linux-gnu/libdl-2.27.so
0x7ffff77de000 0x7ffff77df000 0x1000 0x3000 /lib/x86_64-linux-gnu/libdl-2.27.so
0x7ffff77df000 0x7ffff79c6000 0x1e7000 0x0 /lib/x86_64-linux-gnu/libc-2.27.so
0x7ffff79c6000 0x7ffff7bc6000 0x200000 0x1e7000 /lib/x86_64-linux-gnu/libc-2.27.so
0x7ffff7bc6000 0x7ffff7bca000 0x4000 0x1e7000 /lib/x86_64-linux-gnu/libc-2.27.so
0x7ffff7bca000 0x7ffff7bcc000 0x2000 0x1eb000 /lib/x86_64-linux-gnu/libc-2.27.so
0x7ffff7bcc000 0x7ffff7bd0000 0x4000 0x0
0x7ffff7bd0000 0x7ffff7bd4000 0x4000 0x0 /home/komatsu/stderred/build/libstderred.so
0x7ffff7bd4000 0x7ffff7dd3000 0x1ff000 0x4000 /home/komatsu/stderred/build/libstderred.so
0x7ffff7dd3000 0x7ffff7dd4000 0x1000 0x3000 /home/komatsu/stderred/build/libstderred.so
0x7ffff7dd4000 0x7ffff7dd5000 0x1000 0x4000 /home/komatsu/stderred/build/libstderred.so
0x7ffff7dd5000 0x7ffff7dfc000 0x27000 0x0 /lib/x86_64-linux-gnu/ld-2.27.so
0x7ffff7fd1000 0x7ffff7fd4000 0x3000 0x0
0x7ffff7ff5000 0x7ffff7ff7000 0x2000 0x0
0x7ffff7ff7000 0x7ffff7ffa000 0x3000 0x0 [vvar]
0x7ffff7ffa000 0x7ffff7ffc000 0x2000 0x0 [vdso]
0x7ffff7ffc000 0x7ffff7ffd000 0x1000 0x27000 /lib/x86_64-linux-gnu/ld-2.27.so
0x7ffff7ffd000 0x7ffff7ffe000 0x1000 0x28000 /lib/x86_64-linux-gnu/ld-2.27.so
0x7ffff7ffe000 0x7ffff7fff000 0x1000 0x0
0x7ffffffde000 0x7ffffffff000 0x21000 0x0 [stack]
0xffffffffff600000 0xffffffffff601000 0x1000 0x0 [vsyscall]
(gdb) p main_arena
$1 = {mutex = 0, flags = 0, have_fastchunks = 0, fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, top = 0x0, last_remainder = 0x0,
bins = {0x0 <repeats 254 times>}, binmap = {0, 0, 0, 0}, next = 0x7ffff7bcac40 <main_arena>, next_free = 0x0, attached_threads = 1,
system_mem = 0, max_system_mem = 0}
(gdb) p &main_arena
$2 = (struct malloc_state *) 0x7ffff7bcac40 <main_arena>
(gdb) p *((struct malloc_state *)0x7ffff7bcac40)
$4 = {mutex = 0, flags = 0, have_fastchunks = 0, fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, top = 0x0, last_remainder = 0x0,
bins = {0x0 <repeats 254 times>}, binmap = {0, 0, 0, 0}, next = 0x7ffff7bcac40 <main_arena>, next_free = 0x0, attached_threads = 1,
system_mem = 0, max_system_mem = 0}
アリーナのアドレス「 0x7ffff7bcac40 」は main_arena においては「 libc.2.27.so 」の中にあります。
0x7ffff7bca000 0x7ffff7bcc000 0x2000 0x1eb000 /lib/x86_64-linux-gnu/libc-2.27.so
これを図にすると以下のようになります。
fastbinsY は小さめのフリーチャンクを指すポインター、 bins は大きめのフリーチャンクを指すポインターとなっています。
top はトップチャンク(各アリーナに残された未使用メモリー領域)を指すポインターです。
メインアリーナの特徴はプロセスに一つしかなく、ヒープも一つしかありません。
そのためアリーナを抽象化したオブジェクトである malloc_state は一つしかないですし、ヒープを抽象化した heap_info オブジェクトは無いです。
この理由はメインアリーナはシングルスレッドを想定した作りになっているからです。
ではマルチスレッドが前提のスレッドアリーナはどうなのか図で確認してみましょう。
画像書きながらイマイチだな〜と思うんですが、正直このレベルの複雑さのオブジェクトを表すには言葉が不可欠なんじゃマイカと思うわけです。
例えば heap_info は次の項目で詳しく説明するんで、先走って説明してるようなトンチンカンな説明をしてる気分にさせられんですよね。
それで heap_info はヒープを抽象化したもので、ヒープの先頭にきます。
スレッドアリーナの特性は、複数のヒープを持つことが可能ですんで一つのスレッドアリーナには heap_info が複数あると考えてもよろしいかと思います。
それと malloc_state は(libc.so の中に割り当てられた) main_arena と違って heap_info のすぐ次に配置されます。
では定義を見てみましょう。
malloc.c(https://github.com/MacKomatsu/glibc/blob/release/2.27/master/malloc/malloc.c).
1674 struct malloc_state
1675 {
1676 /* Serialize access. */
1677 __libc_lock_define (, mutex);
1678
1679 /* Flags (formerly in max_fast). */
1680 int flags;
1681
1682 /* Set if the fastbin chunks contain recently inserted free blocks. */
1683 /* Note this is a bool but not all targets support atomics on booleans. */
1684 int have_fastchunks;
1685
1686 /* Fastbins */
1687 mfastbinptr fastbinsY[NFASTBINS];
1688
1689 /* Base of the topmost chunk -- not otherwise kept in a bin */
1690 mchunkptr top;
1691
1692 /* The remainder from the most recent split of a small request */
1693 mchunkptr last_remainder;
1694
1695 /* Normal bins packed as described above */
1696 mchunkptr bins[NBINS * 2 - 2];
1697
1698 /* Bitmap of bins */
1699 unsigned int binmap[BINMAPSIZE];
1700
1701 /* Linked list */
1702 struct malloc_state *next;
1703
1704 /* Linked list for free arenas. Access to this field is serialized
1705 by free_list_lock in arena.c. */
1706 struct malloc_state *next_free;
1707
1708 /* Number of threads attached to this arena. 0 if the arena is on
1709 the free list. Access to this field is serialized by
1710 free_list_lock in arena.c. */
1711 INTERNAL_SIZE_T attached_threads;
1712
1713 /* Memory allocated from the system in this arena. */
1714 INTERNAL_SIZE_T system_mem;
1715 INTERNAL_SIZE_T max_system_mem;
1716 };
この中には mchunkptr という型がありますが、これは malloc_chunk 型を指すポインターです。
malloc_chunk 型はデータを保管したり空き領域を管理する役割を持ちますが、これは後のチャンクの項目で説明しますね。
malloc_state 構造体のポインターには別名として mstate があります。
malloc.h(https://github.com/MacKomatsu/glibc/blob/release/2.27/master/include/malloc.h).
14 struct malloc_state; 15 typedef struct malloc_state *mstate;
それと main_arena については以下のように malloc_state 型として定義されていますね。
malloc.c(https://github.com/MacKomatsu/glibc/blob/release/2.27/master/malloc/malloc.c).
1755 /* There are several instances of this struct ("arenas") in this
1756 malloc. If you are adapting this malloc in a way that does NOT use
1757 a static or mmapped malloc_state, you MUST explicitly zero-fill it
1758 before using. This malloc relies on the property that malloc_state
1759 is initialized to all zeroes (as is true of C statics). */
1760
1761 static struct malloc_state main_arena =
1762 {
1763 .mutex = _LIBC_LOCK_INITIALIZER,
1764 .next = &main_arena,
1765 .attached_threads = 1
1766 };
main_arena をデバッグ開始直後の gdb でチェックできたのはスタティックオブジェクトだからです。
Copyright 2018-2019, by Masaki Komatsu