2017-04-08 60 views
3

的節點被定義如下:該程序爲什麼分配8個頁面,但只能容納2048個大小爲8個字節的節點?

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

通過使用sizeof(struct node)我得知一個節點是8個字節(在XV6)。所以我用malloc來分配一些內存空間來存儲一些節點。 xv6中的單個頁面是4096個字節,如果我有8個頁面,則可以存儲4096個這樣的節點。但是,那不是發生了什麼事情,在這樣的節點之後,如果另一個節點,更多的頁面被分配給當前進程,爲什麼會這樣呢?

// 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

通常,當您分配少量內存時,實際上可能會保留比您指定的更多的內存(系統可能具有分配的最小大小,或者堅持兩個分配大小或其他類似的功能)。保留已分配塊的詳細信息可能會產生額外的開銷,這會使用您要求的部分之外的空間。 – Dmitri

+0

@Dmitri,謝謝。我明白'malloc(n)'使用的字節數多於'n'字節,但是這應該是正確的?這是怎麼發生的?我編輯了這篇文章,我認爲這更清楚地解釋了 –

回答

1

該問題已在評論中得到解答:malloc()需要一些空間來存儲,如何使用內存。

內存處理程序將堆視爲單個大型字節數組(因爲RAM是大多數內存模型中的一個大數組)。 (也有其他內存模型或內存管理器可能會在額外的頁面中存儲一些數據,但爲了簡單起見,我們忽略了這種情況)

作爲一個例子,我們可以想到系統,其中前4個字節用作指針(p0),其中下一個有效塊開始,變量的下一個4字節(size_t,s0)該塊使用多少個字節(我們需要2個變量來檢測2個塊之間的塊何時被釋放)。下一個塊也有一個指針(p1)到下一個(下下的)嵌段和一個可變的塊的大小(s1

此標頭之後是數據,其可以使用,malloc()返回一個指向此標頭後第一個字節的指針。變量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  ?? 

這裏的情況是你ALLOC 2個街區,p1s1是頭變量後的第二塊。您只能使用變量nextvaluemalloc()返回的指針是0x180x28

爲避免爲記憶處理程序使用一半空間,可以在一個步驟中分配一個較大的數組。你可以使用一個struct這樣的:

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

那麼你就需要4 * 4 = 16個字節的總開銷(包括memoryhandler的開銷,並且假設memoryhandler需要每塊8字節的報頭和int,指針和size_t是4個字節)。但是,當您刪除或添加其他值之間的值時,您需要額外的副本或移動開銷。

相關問題