網站虛擬主機空間(內存管理)

準備用一個系列來總結一下內存管理涉及到的相關知識,范圍從底層的數據結構和算法,到上層的API的使用,這裡的內存管理,目前打算主要是側重在堆的管理,本文作為一個引子,先粗略講一下虛擬地址空間、堆管理、arena,接下來會陸續講一下堆管理算法、malloc實現、new/delete等C++內容的相關實現等,但也希望如果以後有時間的話,也可以把棧和甚至和cache相關的內容也加到這個系列裡,現在大概是這麼規劃的,不知道能寫幾篇,先努力寫著看吧。一、虛擬地址空間說內存管理,就必須要先說虛擬地址空間,這是現代程序運行的根本,基本概念大傢都知道就不在這裡贅述瞭,盡量把這部分的精華部分盡量簡單的總結出來,先看一下進程虛擬地址空間的總體佈局,以32位Linux系統為例:基於上圖的虛擬地址空間佈局來簡單說下ELF文件是怎樣映射到進程虛擬地址空間的,ELF文件被組織成如下圖左列出的一系列section,其中具有相同屬性(R/W/E)的section再組成一個segment,以segment為單位映射到進程的虛擬地址空間,其中虛擬地址空間中的segment要做到頁大小對齊,下圖也一同簡要展示瞭虛擬地址空間到物理地址空間的映射,通過MMU完成,具體的細節請大傢網上或者書上查資料,這都是比較基本的概念,這裡就不贅述瞭:其它系統原理類似,都是將可執行程序組織成若幹segment連同用到的動態庫和kernel映射到進程的虛擬地址空間,主要差別在於不同segment映射的起始地址、大小不同等,比如32位Linux系統的Text segment起址是0x08048000,64位Linux系統的Text segment起址是0x00400000,再比如相對32位Linux系統的kernel space是1G,32位Windows的kernel space是2G等等,後面相關內容全部以32位Linux系統為例說明。二、堆從圖1中可以看到堆所處的位置,它位於Data segment的上面,這部分堆空間是程序默認創建的,主要是給程序的主線程用的,在特定的情況下(比如malloc申請大內存的時候、多線程的時候等),堆的內容還會擴展到圖1中的Memory mapping segment區域,假如一共存在三個堆區域,它們的分佈如下圖所示:應用申請堆空間,主要是通過三個系統函數完成的:brk、sbrk、mmap,在前面圖3中,主線程的堆空間是用brk或者sbrk申請的,heap1和heap2這兩個Memory mapping segment是用mmap申請的。其中brk和sbrk使用的是同一個系統調用,根本原理是改變上面圖3中的brk ptr這個指針的位置,mmap的功能很強大,在申請堆空間的時候主要使用它的Anonymous mapping的功能,下面是一個從上到下的簡略調用關系:在堆中,內存被管理的基本單位是塊,glibc中的名字叫chunk,為瞭不引起歧義,這個系列以後全部用chunk這個詞來表示堆中的內存塊,如下圖所示(其中的free chunk會用後續文章介紹的某種算法維護,這裡沒有畫出):三、arena很多人可能沒聽說過這個概念,這是Linux堆管理中常用的一個術語,這個詞的意思是競技場,感覺這個詞用的非常傳神,堆這塊地方可不就是一個競技場麼。下面從glibc實現的角度簡單說下arena,在glibc中,arena的個數是有限制的,限制條件如下:systemarena number32bit2 x cpu_core_number + 164bit8 x cpu_core_number + 1每個線程一定對應一個arena,但是一個arena可以給多個線程使用,同時一個arena可以由一個或者多個圖3中的堆區組成,它們之間的關系如下圖:在glibc中,每一個heap的開始有一個heap_info的描述頭(註意main thread所用到的那個arena對應的heap沒有這個描述頭,也就是緊挨著data segment的那個使用brk/sbrk來動態擴展的heap),定義如下:// malloc/arena.c
typedef struct _heap_info {
// Arena for this heap
struct malloc_state *ar_ptr;
// Previous heap
struct _heap_info *prev;
// Current size in bytes
size_t size;
// Size in bytes that has been mprotected PROT_READ|PROT_WRITE
size_t mprotect_size;
// padding
char pad[];
} heap_info;從上面代碼可以看出,如果一個arena用到多個heap,那麼這些heap通過prev這個指針連接起來,並且通過ar_ptr這個指針指向所屬的arena,arena在glibc中對應的數據結構是malloc_state,定義如下:// malloc/malloc.c
struct malloc_state {
// Flags (formerly in max_fast)
int flags;
// Set if the fastbin chunks contain recently
// inserted free blocks, Note this is a bool
// but not all targets support atomics on booleans
int have_fastchunks;
// Fastbins
mfastbinptr fastbinsY[NFASTBINS];
// Base of the topmost chunk — not otherwise kept in a bin
mchunkptr top;
// The remainder from the most recent split of a small request
mchunkptr last_remainder;
// Normal bins packed as described above
mchunkptr bins[NBINS * 2 – 2];
// Bitmap of bins
unsigned int binmap[BINMAPSIZE];
// Linked list
struct malloc_state *next;
// Linked list for free arenas.
struct malloc_state *next_free;

// Number of threads attached to this arena
INTERNAL_SIZE_T attached_threads;
// Memory allocated from the system in this arena
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
};這裡隻簡單列一下和arena相關的兩個數據結構,其中具體的字段含義等以後將malloc實現的時候再細說,這裡先貼出來大傢好有個基本概念。四、reference這個系列主要參考的資料有下面這些,後續的文章沒有特殊情況的話就不再提及瞭,大傢有興趣的話也可以直接去翻看下面所述的章節:深入理解計算機系統:虛擬存儲器這一章程序員的自我修養:可執行文件的裝載與進程這一章Effective C++:定制new和delete這一章Modern Effective C++:Smart Pointers這一章C++並發編程實戰:C++內存模型和原子類型操作這一章GCC的官方文檔cppreference的內存管理相關函數的manual網上的一些博文: https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/ https://sploitfun.wordpress.com/2015/02/11/syscalls-used-by-malloc https://fantiq.github.io/2019/05/13/malloc%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90-%E5%88%9D%E5%A7%8B%E5%8C%96%E4%B8%8Earena%E7%9A%84%E5%88%9B%E5%BB%BA/ https://introspelliam.github.io/archives/ Safe-Linking – Eliminating a 20 year-old malloc() exploit primitive – Check Point Research tcache 源碼分析及利用思路原文鏈接:https://zhuanlan.zhihu.com/p/374431199 原文作者:月踏

本文出自快速备案,转载时请注明出处及相应链接。

本文永久链接: https://kuaisubeian.cc/49170.html

kuaisubeian