2013-04-13 56 views
1

我正在嘗試爲練習創建自己的malloc()。我得到了下面的代碼從這個thread.Malloc執行 - 困惑

typedef struct free_block { 
    size_t size; 
    struct free_block* next; 
} free_block; 

static free_block free_block_list_head = { 0, 0 }; 

// static const size_t overhead = sizeof(size_t); 

static const size_t align_to = 16; 

void* malloc(size_t size) { 
    size = (size + sizeof(free_block) + (align_to - 1)) & ~ (align_to - 1); 
    free_block* block = free_block_list_head.next; 
    free_block** head = &(free_block_list_head.next); 
    while (block != 0) { 
     if (block->size >= size) { 
      *head = block->next; 
      return ((char*)block) + sizeof(free_block); 
     } 
     head = &(block->next); 
     block = block->next; 
    } 

    block = (free_block*)sbrk(size); 
    block->size = size; 

    return ((char*)block) + sizeof(free_block); 
} 

void free(void* ptr) { 
    free_block* block = (free_block*)(((char*)ptr) - sizeof(free_block)); 
    block->next = free_block_list_head.next; 
    free_block_list_head.next = block; 
} 

我感到困惑治療內存塊的鏈表。在我看來,我們每次需要內存時都會調用sbrk(),並檢查我們以前請求的某些內存是否在此期間未被釋放。

但是我們沒有辦法檢查屬於其他進程的其他內存塊,我們只檢查之前請求的內存並添加到我們的鏈表中。

如果是這樣的話,這是最佳的嗎?這是標準malloc()的工作原理嗎? 有沒有辦法讓我們處理堆上的所有內存?

請解釋我喜歡5,我很難理解這個概念。

+1

「請解釋一下像我5」 - 你不從我的全新鍵盤立即下車你的髒手!? ?? 「 – 2013-04-13 20:12:26

+2

」屬於其他進程的塊「 - 您看不到屬於其他進程的任何內存,只有內核可以(共享內存)。 'malloc'只處理一個進程(可能有多個線程,但只有一個進程)。 – Mat

+3

「但我們無法檢查屬於其他進程的其他內存塊」。呃,好東西,那個。如果你只能訪問其他進程的內存,安全性將會有一個巨大的漏洞。 –

回答

5

擴展進程數據段不影響其他進程。在大多數(最近的)體系結構中,進程內存模型是平坦的,即每個進程具有地址空間(2^322^64字節)。當進程請求額外的內存(頁面)時,會添加一個virtual內存進行處理。實際上,這並不意味着會發生任何物理內存分配,因爲virtual內存可以映射到交換文件,或者在完全使用(地址給予進程但未分配實際資源)之前未映射。內核負責將物理地址映射到virtual,根據需要/每個資源可用性。

該算法的作用是什麼?

當用戶調用malloc時,算法會嘗試查找可用的空白塊。一開始沒有,所以該算法試圖擴展過程數據段。

但是,您可以看到,free未釋放虛擬內存(因爲它不像分配虛擬內存那麼微不足道),而是將此released塊添加到未使用塊的列表中。

因此,當有預覽版塊時,malloc會嘗試重新使用它們而不是extendind數據段。

做標準malloc s如上所述:no。你提供的例子很簡單,但效率很低。有許多不同的算法可用於內存管理:小塊堆(當分配數據達到一定數量時具有性能),特定於線程的分配器(減少從多個線程訪問堆的擁塞),分配器,預分配大塊然後使用它們(類似於上述,但更高效)等。

您可以嘗試goodle爲「內存堆實現」以獲得更多信息