malloc_chunk境界マーキング法と空間多重化

3576 ワード

きょうかいマークほう
ptmallocが割り当てた空間統合はmalloc_を用いたchunk構造で管理、malloc_chunkの構造は初めて奇抜で、注釈を見て、しばらくの間コードを分析して、このような境界マークの設計を発見して、malloc_chunk仮想アドレスが互いに隣接している場合,非常に効率的である.
malloc_chunk構造:
/*
  This struct declaration is misleading (but accurate and necessary).
  It declares a "view" into memory allowing access to necessary
  fields at known offsets from a given base. See explanation below.
*/


struct malloc_chunk {


  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */
  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */


  struct malloc_chunk* fd;         /* double links -- used only if free. */
  struct malloc_chunk* bk;


  /* Only used for large blocks: pointer to next larger size.  */
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  struct malloc_chunk* bk_nextsize;
};

まず、malloc_chunkはすべて仮想アドレスで接続されており、chunkの隣接するchunkのアドレスを知る必要があります.各malloc_chunkはすべて自分のsizeを含んで、また仮想アドレスの前のmalloc_を含みますchunk、ここでは後のmallocを記録する必要はありません.chunkのsizeは、後のヘッダアドレスが現在のmalloc_であるためchunkのヘッダアドレス+size,prev_sizeは前のchunkが空いているときに利用できます.前のchunkが使用されている場合、このprev_sizeの空間は前のchunkに徴用される.現在chunkが使用されている場合、fd,bk,fd_nextsize,bk_nextsizeは、すべて無効で、それらはすべて空きチェーンテーブルに関するポインタであり、これらのポインタの空間はすべて空き空間とされています.ptmallocのコメントには空きmalloc_が描かれていますchunkと割り当てられたmalloc_chunkの構造.
アイドルchunkの構造:
上の図は空きchunkの構造の概略図で、図から現在のmalloc_がわかりますchunkのポインタはchunkポインタで、アドレスが隣接する前のポインタを得るにはchunk-prev_sizeでいいです.アドレスの隣接するポインタ,chunk+sizeを得た.ここでfd,bkポインタはbinにおける空き双方向チェーンテーブルである.これはprev_を通じてsizeはmalloc_をchunkの合併過程は非常に迅速である.
コードからアイドルchunkのマージプロセスを見るか、malloc_consolidateの関数のクリップ:
//     
 
  
if (!prev_inuse(p))
{
    prevsize = p->prev_size;
    size += prevsize;
    p = chunk_at_offset(p, -((long) prevsize));
    unlink(p, bck, fwd);
}

//合併後の
 
  
if (nextchunk != av->top) 
{
    nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
    if (!nextinuse)
    {
        size += nextsize;
        unlink(nextchunk, bck, fwd);
    }
}

コードから分かるように、前のmalloc_をマージします.chunkプロセスでは、前のmalloc_を取得する必要がないことがわかります.chunkのポインタ、合併の過程は大体現在のchunkポインタを前の位置に移動し、同時にsizeを更新し、chunkポインタを対応するbin双方向チェーンテーブルから乾かすことである.マージの過程からprev_を使っただけであることがわかります.sizeは、前のchunkのポインタを使っていません.前のchunkのポインタがあれば、マージプロセスには必ずこのchunkのsizeが必要です.ここではprev_sizeはマージの速度を速めます.prev方向にマージするにはsizeとchunkポインタを更新し、sizeを更新すればnext方向にマージする必要があります.
くうかんふくごう
    malloc_chunkにはsizeが必要で、このchunkの大きさをマークしてmallocの要求を満たすかどうかを決定すると、空きmalloc_に対してchunkではfd,bk,fd_nextsize,bk_nextsizeは必須で、binの空き二重チェーンテーブルです.アイドルでないmalloc_の場合chunkにとってfd,bk,fd_nextsize,bk_nextsizeは役に立たないので,この部分の空間は利用可能な空間として用いられる.ではprev_sizeは複雑で、その状態は仮想アドレスが隣接する前のchunkの状態に依存し、前のchunkが使用状態である場合、このchunkのprev_sizeは意味がなく、マージする必要もないので、前のchunkポインタの位置を知る必要はありません.そのため、この変数の空間は前のchunkに徴用されます.
使用状態のchunk
mallocリクエストのsizeは、構造体のデータサイズを加えてmalloc_chunkのsizeには比べものにならない.
 
  
#define request2size(req) \
    (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? MINSIZE : \
     ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)

上記のマクロから、実際のリクエストのサイズはreqにsize_を加えたものであることがわかります.t次に位置合わせ、ここprev_sizeとsizeは2*size_ではありませんtか、でもnext chunkから贈られたprevを計算します.sizeのsize_t.
まとめ
上の分析からmalloc_chunkのデザインは巧みだprevsizeフィールドは、アドレスが隣接する空きの前のchunkを見つけることができ、空きのchunkをマージするのに便利であり、現在のchunkの前のchunkが使用されている場合、prev_sizeの空間は、前のchunkを利用可能な空間として貸すことができる.