SlideShare ist ein Scribd-Unternehmen logo
1 von 86
malloc の旅( glibc 編)  kosaki @ぬまづ
今日は何の話? ,[object Object],[object Object],[object Object]
Linux  での  process address space model kernel stack text mmap data bss heap 矢印はデータ量の増加と ともに、伸びる方向 使用中 使用中 使用中 今日は、ここ、 heap と呼ばれる領域のお話 low high free free free
古典的 malloc プログラミング言語 C (いわゆる K&R) で紹介された初期の Unix の malloc 実装 使用中 使用中 使用中 free listの head 使用中 ・ free list を使って空きメモリを管理 ・プロセス全体でただ1つの Heap を使う ・ malloc するときに管理領域分だけ多く allocate して先頭に管理領域を付加 ( どこかに管理領域がないと free するときに開放 size がわからない ) ・割り付け strategy  は first fit. union header{ struct{ union header* ptr; unsigned  size;  }s; long alignment; };
malloc のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 このぐらい 欲しい X 足りない 1.まず、 list head から先頭ポインタを get 2.空き領域が十分か調べる ・・・・小さすぎた
malloc のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 X また足りない X このぐらい 欲しい 1.まず、 list head から先頭ポインタを get 2.空き領域が十分か調べる 3.ポインタを list の次の要素に進める 4.また空き領域が十分か調べる うむむ。。また小さい
malloc のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 1.まず、 list head から先頭ポインタを get 2.空き領域が十分か調べる 3.ポインタを list の次の要素に進める 4.また空き領域が十分か調べる 5.また、ポインタを次の要素に進める 6.またまた、空き領域を調べる 今度はあった!! X OK X このぐらい 欲しい
malloc のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 1.まず、 list head から先頭ポインタを get 2.空き領域が十分か調べる 3.ポインタを list の次の要素に進める 4.また空き領域が十分か調べる 5.また、ポインタを次の要素に進める 6.またまた、空き領域を調べる 7.空き領域を2つに分けて、 free list をつなぎなおす 8. list head  を更新 今確保した 領域 最後に探索が失敗した場所 (アロケートされたメモリの 1つ前 の要素) を指すように変更
実は・・・ 使用中 使用中 使用中 free listの head 使用中 実はもう1つ先を探すと、もっといい場所が あったのに・・・ X X このぐらい 欲しい 今確保した 領域
free のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 free したい 領域 1. free list head から最初のポインタをゲット 2.最初の要素の、さらに次のポインタもゲット (next = p->s.ptr) 3. p  <  bp  <  next   が成立しないので次へ bp p next
free のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 free したい 領域 bp p next 1. free list head から最初のポインタをゲット 2.最初の要素の、さらに次のポインタもゲット (next = p->s.ptr) 3. p  <  bp  <  next   が成立しないので次へ 4. p  を次の要素に進める 5 .次のポインタをゲット 6 . p  <  bp  <  next   が成立した
free のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 bp p 7 . p  と bp は隣接していない (p + p->s.size != bp) ので併合しない next 1. free list head から最初のポインタをゲット 2.最初の要素の、さらに次のポインタもゲット (next = p->s.ptr) 3. p  <  bp  <  next   が成立しないので次へ 4. p  を次の要素に進める 5 .次のポインタをゲット 6 . p  <  bp  <  next   が成立した 8. bp と p->s.ptr は隣接しているので (bp + bp->s.size == next) 併合 free したい 領域
free のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 bp p 7 . p  と bp は隣接していない (p + p->s.size != bp) ので併合しない next 1. free list head から最初のポインタをゲット 2.最初の要素の、さらに次のポインタもゲット (next = p->s.ptr) 3. p  <  bp  <  next   が成立しないので次へ 4. p  を次の要素に進める 5 .次のポインタをゲット 6 . p  <  bp  <  next   が成立した 8. bp と p->s.ptr は隣接しているので (bp + bp->s.size == next) 併合 9. free list head  を今開放した要素を 指すよう動かす
次に malloc の特殊なケース heap にまったく空きがなくて heap 自体を拡張するケースを 説明します
ヒープ拡張 使用中 free listの head 使用中 このぐらい 欲しい heap は無限ではないのでいつか足りなくなる X 足りない
ヒープ拡張 使用中 free listの head 使用中 このぐらい 欲しい heap は無限ではないのでいつか足りなくなる X 足りない X
ヒープ拡張 使用中 free listの head 使用中 このぐらい 欲しい heap は無限ではないのでいつか足りなくなる X 足りない X X
ヒープ拡張 使用中 free listの head 使用中 このぐらい 欲しい heap は無限ではないのでいつか足りなくなる X X X ptr と free list の head が再び一致 (一周してしまった)
ヒープ拡張 使用中 free listの head 使用中 このぐらい 欲しい heap は無限ではないのでいつか足りなくなる ここで brk システムコールで heap 領域を一気に 伸ばす brk は heap 最後尾アドレスを変更するAPI heap 最後尾 heap 最後尾
ヒープ拡張 使用中 使用中 heap は無限ではないのでいつか足りなくなる heap 最後尾 今確保した 領域 増えた領域を 2 つにわけ、先頭をユーザに返却。 残りを free list につなぐ free listの head
やや脱線
素朴な brk の実装  ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],new memory data data stack stack 出典:  Lions ’ Commentary on UNIX 増加分 data stack data stack data stack data stack data stack
つまり ,[object Object],[object Object],[object Object]
さて ,[object Object],[object Object],脱線終わり
K&R malloc のいいところ ,[object Object],[object Object],[object Object],[object Object]
K&R malloc のダメなところ ,[object Object],[object Object],[object Object],[object Object]
時代は変わった・・・ ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
最大の問題はなんだろう? ,[object Object],[object Object],[object Object],[object Object],[object Object]
とゆーわけで、時代は best fit アロケータなのである
で、 Just Idea に従って 実装してみる
アドレス順をやめて、 サイズ順にソートしてみる 使用中 使用中 使用中 free listの head 使用中 free の時に、隣接要素と併合することが不可能に・・・・ よけいフラグメンテーションが進みました 本末転倒
やっぱり malloc header に メンバを増やすしかない struct malloc_chunk { INTERNAL_SIZE_T  prev_size;  INTERNAL_SIZE_T  size;  struct malloc_chunk* fd;  struct malloc_chunk* bk; }; 使用中 使用中 使用中 free listの head 使用中 変数名を glibc にあわせたので、だいぶ雰囲気が 変わったけど気にしない address space の prev, next はポインタで 持たずサイズで保持している。
何が変わったのか ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
だめだめです むしろ此処からが本題
ヘッダのダイエットが必要です ,[object Object],[object Object],[object Object],prev_size size fd bk malloc_chunk 構造体にキャストして アクセスするので一見、 fd, bk メンバが あるように見えるが、実はそこは ユーザアプリに使われてしまっているので アクセスするとメモリ破壊 ソースコードからは読み取りにくい・・
ダイエットはつづくよ・・・ ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
[object Object],[object Object],[object Object],32bit なシステムのポインタって・・ 0 31 1 2 ポインタ 0 0
というわけで prev_size size fd bk size fd bk use free free prev_size size use size 1 0 size メンバの再下位 bit を prev が USE 状態かを 記録するビットとして使う (図中の   が最下位ビットを示している) 再下位が0なら prev_size メンバがある。 1 1 free() 関数で chunk_p = (malloc_chunk*)(((char*)ptr) - sizeof(size_t)*2); なんてやってるけど、 size メンバ以外はあるかどうか 分からない 構造体の型とメモリ上のデータ構造がまるで 一致していない香ばしい構造 ->  読みにくさの主原因 ブロック1 ブロック2 ブロック3 ブロック4
時系列で見ると prev_size size fd bk use free free prev_size size fd bk 0 1 1 prev_size size fd bk use free free prev_size size fd bk 0 1 prev_size size fd bk malloc 1 1 prev_size size fd bk prev_size size fd bk 余分に確保するメモリは 4バイトのみ。 request2size()  が  req + sizeof( malloc_chunk)  ではなく req + sizeof(size_t)  なのは ここに原因があった!! malloc 編 malloc ヘッダ malloc ボディ(使用中) malloc ボディ( free ) 当然だけど、 malloc ヘッダから 突き抜けている malloc_chunk メンバはアクセスしたらエライ事になります fd,bk メンバはユーザに使われて しまうので壊される
時系列で見ると use free 1 1 1 1 prev_size size fd bk prev_size size fd bk use prev_size size fd bk prev_size size fd bk free free 1 1 0 1 prev_size size fd bk prev_size size fd bk use prev_size size fd bk prev_size size fd bk free の時に初めて fd, bk, prev_size メンバが 書き込まれる size メンバ以外は、 malloc 時には確保してなかったのだが どうせ free じゃーん。 あいてるじゃーん。 という訳で勝手に使ってる。 ソース上はとってもメモリ破壊ちっく free free 編 ここで prev_in_use フラグが1に
ダイエットは出来たので ,[object Object],[object Object]
ここでアイデア ,[object Object],[object Object]
small bin 16 24 32 40 504 ・・・ size index 2 63 3 4 5 chunks これで小さいサイズの malloc が /* 8 の倍数に切り上げ  */ size = request2size(req);  if( size <= 512 ) { bin_index = size/8; chunk = bins[bin_index].bk; unlink(chunk); /* remove freelist */  return chunk + sizeof(size_t)*2; } このぐらい簡単に終わる 構造体とかはたいてい、このぐらいのサイズにおさまるよね? best fit  どころか、 just fit  アロケータですよ。と 8 8 8 8 8 bin width free list head の配列
さらに改良 ,[object Object],[object Object],[object Object]
large bin 588 652 716 780 ・・・ size index 65 123 66 67 68 64 64 64 64 32K bin width 124 32K 125 250K 126 250k 127 ∞ グラフにするとこんなカンジ bin width bin index bin index が大きくなるにつれ、あつかう block size の幅が指数的に大きくなるように調整 小さいサイズのほうが数が多いので、リストにつながる数を平均化するための施策 大きなサイズ用の リストヘッドも 64 個つくる ・・・ 512 4k ・・・ 750k more
でも ,[object Object],[object Object],[object Object]
その為の mmap です
anonymous mmap とは? ,[object Object],[object Object],[object Object]
またしても size メンバの下位 bit を 0 31 1 2 size 0 0 0 IS_MMAPED PREV_IN_USE 下から2 bit 目を mmap から取得したよーん。 という意味で使うことにする。 この bit が ON なら free list からではなく MMAP で取得 しているので、 free 時に freelist につながずに、 いきなり  munmap() する
データ構造図解 使用中 使用中 使用中 使用中 使用中 (huge) 使用中 (huge) bins ※ 1 見やすくするために、リストをつなぐ線の種類を少しずつ変えてある ※ 2  Huge かつ free 状態はありえない。開放と同時に OS に返却するから
この方法の利点 ,[object Object],[object Object],[object Object],[object Object]
ここまでの結果 ,[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]
でも! それでも! しばしば、 K&R malloc に 負けるんです。これが 実は large size block の malloc – free –malloc – free  と 繰り返す割り当てが遅い
K&R free を振り返ってみる 使用中 使用中 使用中 free listの head 使用中 bp p next 9. free list head  を今開放した要素を 指すよう動かす 今開放した 要素 ここがポイント
キャッシュと局所参照性 ,[object Object],[object Object],[object Object],キャッシュのヒット率重要
バッファの遅延合体 ,[object Object],[object Object],[object Object],[object Object]
バッファの遅延合体 その2 ,[object Object],[object Object],[object Object],[object Object],[object Object]
マクロな視点で話をすると ,[object Object],[object Object],[object Object],[object Object],[object Object]
malloc の 定常状態とバースト状態 バースト状態 バースト状態 このとき、遅延併合が 裏目に出る。 遅延併合リストに要素が 一杯たまるから メモリ使用量 定常状態 遅延併合は裏目にでることもあるが、いちばんありがちな、 定常状態で高速化されるのでモトがとれる
まだもうちょっとだけ 続くんじゃ
みんな大好きマルチスレッド 猫まっしぐら!
素朴な lock malloc(size_t sz){ lock(); ptr = internal_malloc(sz); unlock(); return ptr; } ご冗談でしょう。ファインマンさん たんじゅんに、関数全体を mutex で保護してみた
本当はこうしたい 使用中 使用中 使用中 使用中 使用中 使用中 使用中 使用中 bins 使用中 使用中 使用中 使用中 bins bins スレッド1 スレッド2 スレッド3 スレッド1専用 heap スレッド 2 専用 heap スレッド 3 専用 heap ロックのいらない素敵な世界
それは流石に無理 ,[object Object],[object Object],[object Object]
そこで以下のように実行時に新しい heap を作っていく
Arena 生成 使用中 使用中 使用中 使用中 bins スレッド1 main_arena main_arena ==  今まで説明してきた heap アクセス ロック arena 構造体
使用中 使用中 使用中 使用中 スレッド1 main_arena アクセス ロック アクセス、しかし、ロックとれず bins arena 構造体 スレッド 2 別のスレッドが malloc を同時に呼ぶと、 ロック取得 (mutex_trylock) に失敗 Arena 生成 スレッド2
Arena 生成 スレッド2 使用中 使用中 使用中 使用中 スレッド1 main_arena アクセス ロック スレッド 2 新しい自分専用 heap を mmap で作成 この altanative heap  の仕組みを  arena と呼んでいる。 TLS(thread local strage) に自分用 arena を覚えておくので スレッドが増えるか 1M 使い切るかしない限り二度とバッティングしない bins arena 構造体 とってきたメモリの先頭を  arena 構造体 ( bin 配列などが入っている構造体)として使う 1M free mmap arena 同士は list  でつなげる
Arena 生成 スレッド3 使用中 使用中 使用中 使用中 スレッド1 main_arena スレッド 2 bins arena 構造体 free アクセス スレッド 3 アクセス 次のスレッドも、ロック競合が起きるまでは main_arena を 使い続ける
Arena 生成 スレッド3 使用中 使用中 使用中 使用中 スレッド1 main_arena アクセス ロック スレッド 2 bins arena 構造体 free アクセス スレッド 3 アクセス ロックがぶつかったら・・・・
Arena 生成 スレッド3 使用中 使用中 使用中 使用中 スレッド1 main_arena アクセス ロック スレッド 2 bins arena 構造体 free アクセス スレッド 3 アクセス arena list を、たぐって次々とロック取得をチャレンジ すべて失敗したら、また新しい自分専用 arena を作る。
Arena 生成 スレッド3 使用中 使用中 使用中 使用中 スレッド1 main_arena アクセス ロック スレッド 2 bins arena 構造体 free アクセス スレッド 3 mmap いきなり arena 生成をしないのはスレッド2が すでに終了していたときに、その専用 arena が無駄になるのを防ぐため これにより、スレッド生成直後は色々な arena でロック競合するが そのうちに、 1 スレッド・ 1 アリーナに収束する free
1スレッド:1 Arena の隠れた利点 ,[object Object],[object Object],[object Object],[object Object]
ところで free するときに、自分の所属する arena ってどうやって見つけるんだっけ?
だめアイデア1 ,[object Object],[object Object],[object Object],[object Object],[object Object]
だめアイデア2 ,[object Object],[object Object],[object Object]
だめアイデア3 ,[object Object],[object Object]
結局どうしたか? ,[object Object]
課題 1 ,[object Object],0 31 1 2 size 0 0 0 IS_MMAPED PREV_IN_USE ->  毎度おなじみ size メンバハックのお時間でございま~す♪ IS_NON_MAINARENA
課題 2 ,[object Object],[object Object]
Arena で 1M にそろえる方法 図解 0x100000 0x200000 こういうメモリ確保がしたい しかし mmap では出来ない。 low high use free free 1 M アライン
Arena で 1M にそろえる方法 図解 0x100000 0x200000 2 倍のサイズで mmap ただし PROT_NONE 0x100000 0x200000 余分な場所を munmap READ も WRITE も EXEC も不可なメモリ確保というのは メモリを確保しないが、アドレススペースは確保するというのと同義 1M アラインされた場所から size 1M で  PROT_READ | PROT_WRITE | PROT_EXEC  で  remap. 0x100000 0x200000
まとめ ,[object Object],[object Object],[object Object],[object Object]
glibc malloc のダメなところ ,[object Object],[object Object],[object Object]
終わりに変えて ,[object Object],[object Object],[object Object],[object Object],[object Object]
ご清聴ありがとうございました! つかれた~  (≧ω≦) ゞ

Weitere ähnliche Inhalte

Was ist angesagt?

SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」Takuto Wada
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門大樹 小倉
 
RSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpRSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpsonickun
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safeKumazaki Hiroki
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Akihiro Suda
 
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021Hiroshi Tokumaru
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチンyohhoy
 
TRICK 2022 Results
TRICK 2022 ResultsTRICK 2022 Results
TRICK 2022 Resultsmametter
 
AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解MITSUNARI Shigeo
 
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーWhere狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーyoku0825
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説murachue
 
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-Takuya Akiba
 
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~ CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~ SEGADevTech
 
MCC CTF講習会 pwn編
MCC CTF講習会 pwn編MCC CTF講習会 pwn編
MCC CTF講習会 pwn編hama7230
 
できる!並列・並行プログラミング
できる!並列・並行プログラミングできる!並列・並行プログラミング
できる!並列・並行プログラミングPreferred Networks
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門Fixstars Corporation
 

Was ist angesagt? (20)

SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門
 
Docker Compose 徹底解説
Docker Compose 徹底解説Docker Compose 徹底解説
Docker Compose 徹底解説
 
RSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjpRSA暗号運用でやってはいけない n のこと #ssmjp
RSA暗号運用でやってはいけない n のこと #ssmjp
 
llvm入門
llvm入門llvm入門
llvm入門
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safe
 
明日使えないすごいビット演算
明日使えないすごいビット演算明日使えないすごいビット演算
明日使えないすごいビット演算
 
Marp Tutorial
Marp TutorialMarp Tutorial
Marp Tutorial
 
Dockerからcontainerdへの移行
Dockerからcontainerdへの移行Dockerからcontainerdへの移行
Dockerからcontainerdへの移行
 
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
 
TRICK 2022 Results
TRICK 2022 ResultsTRICK 2022 Results
TRICK 2022 Results
 
AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解AVX-512(フォーマット)詳解
AVX-512(フォーマット)詳解
 
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーWhere狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説
 
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
乱択データ構造の最新事情 -MinHash と HyperLogLog の最近の進歩-
 
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~ CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
CEDEC2021 ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~
 
MCC CTF講習会 pwn編
MCC CTF講習会 pwn編MCC CTF講習会 pwn編
MCC CTF講習会 pwn編
 
できる!並列・並行プログラミング
できる!並列・並行プログラミングできる!並列・並行プログラミング
できる!並列・並行プログラミング
 
いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門いまさら聞けない!CUDA高速化入門
いまさら聞けない!CUDA高速化入門
 

Andere mochten auch

高度に最適化された移植可能なメモリマネージャ
高度に最適化された移植可能なメモリマネージャ高度に最適化された移植可能なメモリマネージャ
高度に最適化された移植可能なメモリマネージャDADA246
 
Binary exploitation - AIS3
Binary exploitation - AIS3Binary exploitation - AIS3
Binary exploitation - AIS3Angel Boy
 
SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)
SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)
SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)Sehan Lee
 
Bug hunting through_reverse_engineering
Bug hunting through_reverse_engineeringBug hunting through_reverse_engineering
Bug hunting through_reverse_engineeringarif
 
Heap exploitation
Heap exploitationHeap exploitation
Heap exploitationAngel Boy
 
Advanced heap exploitaion
Advanced heap exploitaionAdvanced heap exploitaion
Advanced heap exploitaionAngel Boy
 
Sigreturn Oriented Programming
Sigreturn Oriented ProgrammingSigreturn Oriented Programming
Sigreturn Oriented ProgrammingAngel Boy
 
Play with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit TechniquePlay with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit TechniqueAngel Boy
 
Introduction to Reverse Engineering
Introduction to Reverse EngineeringIntroduction to Reverse Engineering
Introduction to Reverse EngineeringGopinath Chintala
 
Reverse engineering
Reverse  engineeringReverse  engineering
Reverse engineeringYuffie Valen
 
Introduction to Reverse Engineering
Introduction to Reverse EngineeringIntroduction to Reverse Engineering
Introduction to Reverse EngineeringDobromir Enchev
 
Reverse Engineering
Reverse EngineeringReverse Engineering
Reverse Engineeringdswanson
 
Reverse engineering & its application
Reverse engineering & its applicationReverse engineering & its application
Reverse engineering & its applicationmapqrs
 
Reverse engineering
Reverse engineeringReverse engineering
Reverse engineeringananya0122
 
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017Carol Smith
 

Andere mochten auch (16)

高度に最適化された移植可能なメモリマネージャ
高度に最適化された移植可能なメモリマネージャ高度に最適化された移植可能なメモリマネージャ
高度に最適化された移植可能なメモリマネージャ
 
Binary exploitation - AIS3
Binary exploitation - AIS3Binary exploitation - AIS3
Binary exploitation - AIS3
 
SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)
SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)
SECCON 2016 Online CTF [Memory Analysis] Write-Up (ver.korean)
 
Bug hunting through_reverse_engineering
Bug hunting through_reverse_engineeringBug hunting through_reverse_engineering
Bug hunting through_reverse_engineering
 
Heap exploitation
Heap exploitationHeap exploitation
Heap exploitation
 
Advanced heap exploitaion
Advanced heap exploitaionAdvanced heap exploitaion
Advanced heap exploitaion
 
Sigreturn Oriented Programming
Sigreturn Oriented ProgrammingSigreturn Oriented Programming
Sigreturn Oriented Programming
 
Play with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit TechniquePlay with FILE Structure - Yet Another Binary Exploit Technique
Play with FILE Structure - Yet Another Binary Exploit Technique
 
Introduction to Reverse Engineering
Introduction to Reverse EngineeringIntroduction to Reverse Engineering
Introduction to Reverse Engineering
 
Reverse engineering
Reverse engineeringReverse engineering
Reverse engineering
 
Reverse engineering
Reverse  engineeringReverse  engineering
Reverse engineering
 
Introduction to Reverse Engineering
Introduction to Reverse EngineeringIntroduction to Reverse Engineering
Introduction to Reverse Engineering
 
Reverse Engineering
Reverse EngineeringReverse Engineering
Reverse Engineering
 
Reverse engineering & its application
Reverse engineering & its applicationReverse engineering & its application
Reverse engineering & its application
 
Reverse engineering
Reverse engineeringReverse engineering
Reverse engineering
 
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
AI and Machine Learning Demystified by Carol Smith at Midwest UX 2017
 

Ähnlich wie Glibc malloc internal

Google Perf Tools (tcmalloc) の使い方
Google Perf Tools (tcmalloc) の使い方Google Perf Tools (tcmalloc) の使い方
Google Perf Tools (tcmalloc) の使い方Kazuki Ohta
 
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Ransui Iso
 
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Ransui Iso
 
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Ransui Iso
 
Javaで作る超簡易x86エミュレータ
Javaで作る超簡易x86エミュレータJavaで作る超簡易x86エミュレータ
Javaで作る超簡易x86エミュレータDaisuke Kamikawa
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Rubymitim
 
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったかm2ym
 
PHP基礎勉強会
PHP基礎勉強会PHP基礎勉強会
PHP基礎勉強会Yuji Otani
 
Linux の hugepage の開発動向
Linux の hugepage の開発動向Linux の hugepage の開発動向
Linux の hugepage の開発動向Naoya Horiguchi
 
CRF を使った Web 本文抽出
CRF を使った Web 本文抽出CRF を使った Web 本文抽出
CRF を使った Web 本文抽出Shuyo Nakatani
 
"Hello World!" から始める Calc で LibreOffice Basic
"Hello World!" から始める Calc で LibreOffice Basic"Hello World!" から始める Calc で LibreOffice Basic
"Hello World!" から始める Calc で LibreOffice Basic78tch
 
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~infinite_loop
 
【学習メモ#4th】12ステップで作る組込みOS自作入門
【学習メモ#4th】12ステップで作る組込みOS自作入門【学習メモ#4th】12ステップで作る組込みOS自作入門
【学習メモ#4th】12ステップで作る組込みOS自作入門sandai
 
C++ lecture-0
C++ lecture-0C++ lecture-0
C++ lecture-0sunaemon
 
Programming camp code reading
Programming camp code readingProgramming camp code reading
Programming camp code readingHiro Yoshioka
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, CodereadingHiro Yoshioka
 
PowerShellが苦手だった男がPowerShellを愛するようになるまで
PowerShellが苦手だった男がPowerShellを愛するようになるまでPowerShellが苦手だった男がPowerShellを愛するようになるまで
PowerShellが苦手だった男がPowerShellを愛するようになるまでKazuhiro Matsushima
 
Buffer overflow
Buffer overflowBuffer overflow
Buffer overflowionis111
 
Essential Scala 第5章 シーケンス処理
Essential Scala 第5章 シーケンス処理Essential Scala 第5章 シーケンス処理
Essential Scala 第5章 シーケンス処理Takuya Tsuchida
 

Ähnlich wie Glibc malloc internal (20)

Google Perf Tools (tcmalloc) の使い方
Google Perf Tools (tcmalloc) の使い方Google Perf Tools (tcmalloc) の使い方
Google Perf Tools (tcmalloc) の使い方
 
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1
 
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3
 
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6
 
Javaで作る超簡易x86エミュレータ
Javaで作る超簡易x86エミュレータJavaで作る超簡易x86エミュレータ
Javaで作る超簡易x86エミュレータ
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Ruby
 
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
 
Nmap 9つの真実
Nmap 9つの真実Nmap 9つの真実
Nmap 9つの真実
 
PHP基礎勉強会
PHP基礎勉強会PHP基礎勉強会
PHP基礎勉強会
 
Linux の hugepage の開発動向
Linux の hugepage の開発動向Linux の hugepage の開発動向
Linux の hugepage の開発動向
 
CRF を使った Web 本文抽出
CRF を使った Web 本文抽出CRF を使った Web 本文抽出
CRF を使った Web 本文抽出
 
"Hello World!" から始める Calc で LibreOffice Basic
"Hello World!" から始める Calc で LibreOffice Basic"Hello World!" から始める Calc で LibreOffice Basic
"Hello World!" から始める Calc で LibreOffice Basic
 
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
大規模ソーシャルゲームを支える技術~PHP+MySQLを使った高負荷対策~
 
【学習メモ#4th】12ステップで作る組込みOS自作入門
【学習メモ#4th】12ステップで作る組込みOS自作入門【学習メモ#4th】12ステップで作る組込みOS自作入門
【学習メモ#4th】12ステップで作る組込みOS自作入門
 
C++ lecture-0
C++ lecture-0C++ lecture-0
C++ lecture-0
 
Programming camp code reading
Programming camp code readingProgramming camp code reading
Programming camp code reading
 
Programming camp 2008, Codereading
Programming camp 2008, CodereadingProgramming camp 2008, Codereading
Programming camp 2008, Codereading
 
PowerShellが苦手だった男がPowerShellを愛するようになるまで
PowerShellが苦手だった男がPowerShellを愛するようになるまでPowerShellが苦手だった男がPowerShellを愛するようになるまで
PowerShellが苦手だった男がPowerShellを愛するようになるまで
 
Buffer overflow
Buffer overflowBuffer overflow
Buffer overflow
 
Essential Scala 第5章 シーケンス処理
Essential Scala 第5章 シーケンス処理Essential Scala 第5章 シーケンス処理
Essential Scala 第5章 シーケンス処理
 

Kürzlich hochgeladen

論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNetToru Tamaki
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...Toru Tamaki
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものですiPride Co., Ltd.
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdftaisei2219
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A surveyToru Tamaki
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Yuma Ohgami
 

Kürzlich hochgeladen (9)

論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet論文紹介:Automated Classification of Model Errors on ImageNet
論文紹介:Automated Classification of Model Errors on ImageNet
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
論文紹介:Content-Aware Token Sharing for Efficient Semantic Segmentation With Vis...
 
SOPを理解する 2024/04/19 の勉強会で発表されたものです
SOPを理解する       2024/04/19 の勉強会で発表されたものですSOPを理解する       2024/04/19 の勉強会で発表されたものです
SOPを理解する 2024/04/19 の勉強会で発表されたものです
 
TSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdfTSAL operation mechanism and circuit diagram.pdf
TSAL operation mechanism and circuit diagram.pdf
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey論文紹介:Semantic segmentation using Vision Transformers: A survey
論文紹介:Semantic segmentation using Vision Transformers: A survey
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
Open Source UN-Conference 2024 Kawagoe - 独自OS「DaisyOS GB」の紹介
 

Glibc malloc internal

  • 1. malloc の旅( glibc 編) kosaki @ぬまづ
  • 2.
  • 3. Linux での process address space model kernel stack text mmap data bss heap 矢印はデータ量の増加と ともに、伸びる方向 使用中 使用中 使用中 今日は、ここ、 heap と呼ばれる領域のお話 low high free free free
  • 4. 古典的 malloc プログラミング言語 C (いわゆる K&R) で紹介された初期の Unix の malloc 実装 使用中 使用中 使用中 free listの head 使用中 ・ free list を使って空きメモリを管理 ・プロセス全体でただ1つの Heap を使う ・ malloc するときに管理領域分だけ多く allocate して先頭に管理領域を付加 ( どこかに管理領域がないと free するときに開放 size がわからない ) ・割り付け strategy は first fit. union header{ struct{ union header* ptr; unsigned size; }s; long alignment; };
  • 5. malloc のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 このぐらい 欲しい X 足りない 1.まず、 list head から先頭ポインタを get 2.空き領域が十分か調べる ・・・・小さすぎた
  • 6. malloc のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 X また足りない X このぐらい 欲しい 1.まず、 list head から先頭ポインタを get 2.空き領域が十分か調べる 3.ポインタを list の次の要素に進める 4.また空き領域が十分か調べる うむむ。。また小さい
  • 7. malloc のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 1.まず、 list head から先頭ポインタを get 2.空き領域が十分か調べる 3.ポインタを list の次の要素に進める 4.また空き領域が十分か調べる 5.また、ポインタを次の要素に進める 6.またまた、空き領域を調べる 今度はあった!! X OK X このぐらい 欲しい
  • 8. malloc のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 1.まず、 list head から先頭ポインタを get 2.空き領域が十分か調べる 3.ポインタを list の次の要素に進める 4.また空き領域が十分か調べる 5.また、ポインタを次の要素に進める 6.またまた、空き領域を調べる 7.空き領域を2つに分けて、 free list をつなぎなおす 8. list head を更新 今確保した 領域 最後に探索が失敗した場所 (アロケートされたメモリの 1つ前 の要素) を指すように変更
  • 9. 実は・・・ 使用中 使用中 使用中 free listの head 使用中 実はもう1つ先を探すと、もっといい場所が あったのに・・・ X X このぐらい 欲しい 今確保した 領域
  • 10. free のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 free したい 領域 1. free list head から最初のポインタをゲット 2.最初の要素の、さらに次のポインタもゲット (next = p->s.ptr) 3. p < bp < next が成立しないので次へ bp p next
  • 11. free のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 free したい 領域 bp p next 1. free list head から最初のポインタをゲット 2.最初の要素の、さらに次のポインタもゲット (next = p->s.ptr) 3. p < bp < next が成立しないので次へ 4. p を次の要素に進める 5 .次のポインタをゲット 6 . p < bp < next が成立した
  • 12. free のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 bp p 7 . p と bp は隣接していない (p + p->s.size != bp) ので併合しない next 1. free list head から最初のポインタをゲット 2.最初の要素の、さらに次のポインタもゲット (next = p->s.ptr) 3. p < bp < next が成立しないので次へ 4. p を次の要素に進める 5 .次のポインタをゲット 6 . p < bp < next が成立した 8. bp と p->s.ptr は隣接しているので (bp + bp->s.size == next) 併合 free したい 領域
  • 13. free のアルゴリズム 使用中 使用中 使用中 free listの head 使用中 bp p 7 . p と bp は隣接していない (p + p->s.size != bp) ので併合しない next 1. free list head から最初のポインタをゲット 2.最初の要素の、さらに次のポインタもゲット (next = p->s.ptr) 3. p < bp < next が成立しないので次へ 4. p を次の要素に進める 5 .次のポインタをゲット 6 . p < bp < next が成立した 8. bp と p->s.ptr は隣接しているので (bp + bp->s.size == next) 併合 9. free list head を今開放した要素を 指すよう動かす
  • 14. 次に malloc の特殊なケース heap にまったく空きがなくて heap 自体を拡張するケースを 説明します
  • 15. ヒープ拡張 使用中 free listの head 使用中 このぐらい 欲しい heap は無限ではないのでいつか足りなくなる X 足りない
  • 16. ヒープ拡張 使用中 free listの head 使用中 このぐらい 欲しい heap は無限ではないのでいつか足りなくなる X 足りない X
  • 17. ヒープ拡張 使用中 free listの head 使用中 このぐらい 欲しい heap は無限ではないのでいつか足りなくなる X 足りない X X
  • 18. ヒープ拡張 使用中 free listの head 使用中 このぐらい 欲しい heap は無限ではないのでいつか足りなくなる X X X ptr と free list の head が再び一致 (一周してしまった)
  • 19. ヒープ拡張 使用中 free listの head 使用中 このぐらい 欲しい heap は無限ではないのでいつか足りなくなる ここで brk システムコールで heap 領域を一気に 伸ばす brk は heap 最後尾アドレスを変更するAPI heap 最後尾 heap 最後尾
  • 20. ヒープ拡張 使用中 使用中 heap は無限ではないのでいつか足りなくなる heap 最後尾 今確保した 領域 増えた領域を 2 つにわけ、先頭をユーザに返却。 残りを free list につなぐ free listの head
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29. とゆーわけで、時代は best fit アロケータなのである
  • 30. で、 Just Idea に従って 実装してみる
  • 31. アドレス順をやめて、 サイズ順にソートしてみる 使用中 使用中 使用中 free listの head 使用中 free の時に、隣接要素と併合することが不可能に・・・・ よけいフラグメンテーションが進みました 本末転倒
  • 32. やっぱり malloc header に メンバを増やすしかない struct malloc_chunk { INTERNAL_SIZE_T prev_size; INTERNAL_SIZE_T size; struct malloc_chunk* fd; struct malloc_chunk* bk; }; 使用中 使用中 使用中 free listの head 使用中 変数名を glibc にあわせたので、だいぶ雰囲気が 変わったけど気にしない address space の prev, next はポインタで 持たずサイズで保持している。
  • 33.
  • 35.
  • 36.
  • 37.
  • 38. というわけで prev_size size fd bk size fd bk use free free prev_size size use size 1 0 size メンバの再下位 bit を prev が USE 状態かを 記録するビットとして使う (図中の   が最下位ビットを示している) 再下位が0なら prev_size メンバがある。 1 1 free() 関数で chunk_p = (malloc_chunk*)(((char*)ptr) - sizeof(size_t)*2); なんてやってるけど、 size メンバ以外はあるかどうか 分からない 構造体の型とメモリ上のデータ構造がまるで 一致していない香ばしい構造 -> 読みにくさの主原因 ブロック1 ブロック2 ブロック3 ブロック4
  • 39. 時系列で見ると prev_size size fd bk use free free prev_size size fd bk 0 1 1 prev_size size fd bk use free free prev_size size fd bk 0 1 prev_size size fd bk malloc 1 1 prev_size size fd bk prev_size size fd bk 余分に確保するメモリは 4バイトのみ。 request2size() が req + sizeof( malloc_chunk) ではなく req + sizeof(size_t) なのは ここに原因があった!! malloc 編 malloc ヘッダ malloc ボディ(使用中) malloc ボディ( free ) 当然だけど、 malloc ヘッダから 突き抜けている malloc_chunk メンバはアクセスしたらエライ事になります fd,bk メンバはユーザに使われて しまうので壊される
  • 40. 時系列で見ると use free 1 1 1 1 prev_size size fd bk prev_size size fd bk use prev_size size fd bk prev_size size fd bk free free 1 1 0 1 prev_size size fd bk prev_size size fd bk use prev_size size fd bk prev_size size fd bk free の時に初めて fd, bk, prev_size メンバが 書き込まれる size メンバ以外は、 malloc 時には確保してなかったのだが どうせ free じゃーん。 あいてるじゃーん。 という訳で勝手に使ってる。 ソース上はとってもメモリ破壊ちっく free free 編 ここで prev_in_use フラグが1に
  • 41.
  • 42.
  • 43. small bin 16 24 32 40 504 ・・・ size index 2 63 3 4 5 chunks これで小さいサイズの malloc が /* 8 の倍数に切り上げ */ size = request2size(req); if( size <= 512 ) { bin_index = size/8; chunk = bins[bin_index].bk; unlink(chunk); /* remove freelist */ return chunk + sizeof(size_t)*2; } このぐらい簡単に終わる 構造体とかはたいてい、このぐらいのサイズにおさまるよね? best fit どころか、 just fit アロケータですよ。と 8 8 8 8 8 bin width free list head の配列
  • 44.
  • 45. large bin 588 652 716 780 ・・・ size index 65 123 66 67 68 64 64 64 64 32K bin width 124 32K 125 250K 126 250k 127 ∞ グラフにするとこんなカンジ bin width bin index bin index が大きくなるにつれ、あつかう block size の幅が指数的に大きくなるように調整 小さいサイズのほうが数が多いので、リストにつながる数を平均化するための施策 大きなサイズ用の リストヘッドも 64 個つくる ・・・ 512 4k ・・・ 750k more
  • 46.
  • 48.
  • 49. またしても size メンバの下位 bit を 0 31 1 2 size 0 0 0 IS_MMAPED PREV_IN_USE 下から2 bit 目を mmap から取得したよーん。 という意味で使うことにする。 この bit が ON なら free list からではなく MMAP で取得 しているので、 free 時に freelist につながずに、 いきなり munmap() する
  • 50. データ構造図解 使用中 使用中 使用中 使用中 使用中 (huge) 使用中 (huge) bins ※ 1 見やすくするために、リストをつなぐ線の種類を少しずつ変えてある ※ 2 Huge かつ free 状態はありえない。開放と同時に OS に返却するから
  • 51.
  • 52.
  • 53. でも! それでも! しばしば、 K&R malloc に 負けるんです。これが 実は large size block の malloc – free –malloc – free と 繰り返す割り当てが遅い
  • 54. K&R free を振り返ってみる 使用中 使用中 使用中 free listの head 使用中 bp p next 9. free list head を今開放した要素を 指すよう動かす 今開放した 要素 ここがポイント
  • 55.
  • 56.
  • 57.
  • 58.
  • 59. malloc の 定常状態とバースト状態 バースト状態 バースト状態 このとき、遅延併合が 裏目に出る。 遅延併合リストに要素が 一杯たまるから メモリ使用量 定常状態 遅延併合は裏目にでることもあるが、いちばんありがちな、 定常状態で高速化されるのでモトがとれる
  • 62. 素朴な lock malloc(size_t sz){ lock(); ptr = internal_malloc(sz); unlock(); return ptr; } ご冗談でしょう。ファインマンさん たんじゅんに、関数全体を mutex で保護してみた
  • 63. 本当はこうしたい 使用中 使用中 使用中 使用中 使用中 使用中 使用中 使用中 bins 使用中 使用中 使用中 使用中 bins bins スレッド1 スレッド2 スレッド3 スレッド1専用 heap スレッド 2 専用 heap スレッド 3 専用 heap ロックのいらない素敵な世界
  • 64.
  • 66. Arena 生成 使用中 使用中 使用中 使用中 bins スレッド1 main_arena main_arena == 今まで説明してきた heap アクセス ロック arena 構造体
  • 67. 使用中 使用中 使用中 使用中 スレッド1 main_arena アクセス ロック アクセス、しかし、ロックとれず bins arena 構造体 スレッド 2 別のスレッドが malloc を同時に呼ぶと、 ロック取得 (mutex_trylock) に失敗 Arena 生成 スレッド2
  • 68. Arena 生成 スレッド2 使用中 使用中 使用中 使用中 スレッド1 main_arena アクセス ロック スレッド 2 新しい自分専用 heap を mmap で作成 この altanative heap の仕組みを arena と呼んでいる。 TLS(thread local strage) に自分用 arena を覚えておくので スレッドが増えるか 1M 使い切るかしない限り二度とバッティングしない bins arena 構造体 とってきたメモリの先頭を arena 構造体 ( bin 配列などが入っている構造体)として使う 1M free mmap arena 同士は list でつなげる
  • 69. Arena 生成 スレッド3 使用中 使用中 使用中 使用中 スレッド1 main_arena スレッド 2 bins arena 構造体 free アクセス スレッド 3 アクセス 次のスレッドも、ロック競合が起きるまでは main_arena を 使い続ける
  • 70. Arena 生成 スレッド3 使用中 使用中 使用中 使用中 スレッド1 main_arena アクセス ロック スレッド 2 bins arena 構造体 free アクセス スレッド 3 アクセス ロックがぶつかったら・・・・
  • 71. Arena 生成 スレッド3 使用中 使用中 使用中 使用中 スレッド1 main_arena アクセス ロック スレッド 2 bins arena 構造体 free アクセス スレッド 3 アクセス arena list を、たぐって次々とロック取得をチャレンジ すべて失敗したら、また新しい自分専用 arena を作る。
  • 72. Arena 生成 スレッド3 使用中 使用中 使用中 使用中 スレッド1 main_arena アクセス ロック スレッド 2 bins arena 構造体 free アクセス スレッド 3 mmap いきなり arena 生成をしないのはスレッド2が すでに終了していたときに、その専用 arena が無駄になるのを防ぐため これにより、スレッド生成直後は色々な arena でロック競合するが そのうちに、 1 スレッド・ 1 アリーナに収束する free
  • 73.
  • 74. ところで free するときに、自分の所属する arena ってどうやって見つけるんだっけ?
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81. Arena で 1M にそろえる方法 図解 0x100000 0x200000 こういうメモリ確保がしたい しかし mmap では出来ない。 low high use free free 1 M アライン
  • 82. Arena で 1M にそろえる方法 図解 0x100000 0x200000 2 倍のサイズで mmap ただし PROT_NONE 0x100000 0x200000 余分な場所を munmap READ も WRITE も EXEC も不可なメモリ確保というのは メモリを確保しないが、アドレススペースは確保するというのと同義 1M アラインされた場所から size 1M で PROT_READ | PROT_WRITE | PROT_EXEC で remap. 0x100000 0x200000
  • 83.
  • 84.
  • 85.