2017-04-08 7 views
3

ノードが定義されている:なぜこのプログラムは8ページを割り当てますが、サイズが8バイトの2048ノードに収まるだけですか?次のように

struct node{ 
     int value; 
     struct node *next; 
    }; 

sizeof(struct node)を使用することにより、私は、ノードが(xv6に)8バイトであることを知ります。だから私はmallocいくつかのノードを格納するためにいくつかのメモリ空間を割り当てて使用します。 xv6の単一ページは4096バイトです.8ページあれば、4096個のノードを格納できます。しかし、それは起こっていません。 2048のようなノードの場合、別の場合は、現在のプロセスに割り当てられたページが増えています。それはなぜですか?

// Now display how many pages are allocated to the process 
    // Suppose there is a system call named memcount(), it is given by 
    // my professor, I wouldn't think there's any problem with that 
    // 
    memcount(); // which prints 3, meaning that initially, without 
       // allocaing anything, 3 pages = 12288 bytes of memory allocated 

    for(i = 0; i < 2048; ++i){ 
     struct node *nd = (struct node *)malloc(sizeof(struct node)); 
    } 

    memcount(); // which prints 11, so 8 more pages are allocated 

    // If we allocated 1 more node 
    struct node *nd = (struct node *)malloc(sizeof(struct node)); 
    memcount(); // which prints 19, another 8 pages are allocated 

私はとても混乱しています。最初の8ページには多くのスペースが残っていませんか?単一ノードのサイズはわずか8バイトなので、プロセスに割り当てられるページが増えているのはなぜですか?

+5

'malloc(X)'は、 'X'バイト以上のメモリを使います。いくつかのメモリはヒープ制御構造のために秘密に割り当てられています。 – DyZ

+0

一般的に、少量のメモリを割り当てると、指定した以上の容量を実際に予約することができます(システムは割り当てられる最小サイズを持つか、2つの割り当てサイズのいずれか、またはその他のものを要求します)。また、割り当てられたブロックの詳細を保持するために追加のオーバーヘッドが存在する可能性があります。割り当てられたブロックの外側にスペースを使用します。 – Dmitri

+0

@ドミトリ、ありがとう。私は 'malloc(n)'が 'n'バイトよりも少し多く使うことを理解していますが、それはちょっと正しいでしょうか?どうしてそんなことが起こるの?私はポストを編集した、私はそれがより明確に説明すると思う。 –

答えて

1

質問にはすでに回答がありました。コメント:malloc()は、メモリの使用方法を保存するためのスペースが必要です。

メモリハンドラはヒープを単一の大きなバイト配列と見なします(RAMはほとんどのメモリモデルでは1つの大きな配列なので)。 (他のメモリモデルもありますし、memorymanagerが余分なページにデータを格納しているかもしれませんが、単純にするために無視します)。

例として、最初の4バイトは変数(size_t,)の次の有効なブロックが開始され、次の4バイトがこのブロックに使用されるポインタ(p0)です(2つのブロック間のブロックが解放されたときを検出するには2つの変数が必要です)。このヘッダーは、使用できるデータ、malloc()戻りAされた後、次のブロックは、ブロックとブロック(s1)のサイズ変数(次の次)次

へのポインタ(p1)を有しますこのヘッダの後の最初のバイトへのポインタ。変数s0には、要求したバイト数が格納されます。新しいmalloc()後、新しいヘッダーは、最初のブロックの後に作成され、P0は、このヘッダを指すようになります。ここでは

Address: 0x10 0x14 0x18 0x1B 0x20 0x24 0x28 ... 
Name:  p0  s0  value next p1  s1  value... 
Value:  0x20 8  ??  0x28 0  8  ?? 

は、あなたが2つのブロックをアロケーション後の状況で、p1s1は、ヘッダの変数です2番目のブロックの変数nextvalueのみを使用できます。 malloc()が返すポインタは0x180x28です。

メモリハンドラの半分のスペースを使用しないようにするには、1ステップで大きなアレイを割り当てることができます。あなたは、このようなstructを使用することができます、そして、あなたがMemoryHandlerののオーバーヘッドを含む4 * 4 = 16バイトの合計オーバーヘッド(、必要とMemoryHandlerの必要性8バイトのブロックごとにヘッダとintを想定します

struct Node_T 
    { 
    int values[512]; 
    size_t usedValues; 
    struct Node_T *next; 
    } 

ポインタとsize_tは4バイトです)。しかし、他の値の間で値を削除または追加するときは、余分なコピーやオーバーヘッドの移動が必要です。

関連する問題