用戶空間(3GB on x86_64)自低向高:
+------------------+ 0x00007fffffffffff (用戶空間上限)
| Stack | ↓ 向下增長
| (main thread) |
|------------------|
| ... |
| Shared Libs | (ld.so, libc, etc.)
|------------------|
| Heap | ↑ 向上增長 (brk)
|------------------|
| BSS |
| Data |
| Text (Code) |
+------------------+ 0x00000000400000 (典型基址)
mm_struct (include/linux/mm_types.h)struct mm_struct {
struct vm_area_struct *mmap; // VMA 鏈表/紅黑樹
struct rb_root mm_rb; // VMA 紅黑樹根
pgd_t *pgd; // 頁全局目錄基址
atomic_t mm_users; // 用戶空間引用計數
atomic_t mm_count; // 結構體引用計數
int map_count; // VMA 數量
unsigned long start_code, end_code;
unsigned long start_data, end_data;
unsigned long start_brk, brk, start_stack; // 堆/棧邊界
// ...
};
start_brk:堆起始地址(靜態數據段結束處)brk:堆當前頂端地址(動態變化)mmap:記錄所有已映射區域(VMA)缺頁中斷時,內核分配物理頁、建立頁表映射、更新 VMA。
struct malloc_chunk {
size_t prev_size; // 前一塊大小(若空閒)
size_t size; // 當前塊大小 | 標誌位
struct malloc_chunk *fd; // 雙向鏈表指針
struct malloc_chunk *bk;
struct malloc_chunk *fd_nextsize; // large bin 用
struct malloc_chunk *bk_nextsize;
};
brk() 或 mmap() 擴展堆| 系統調用 | 用途 | 觸發條件 |
|---|---|---|
brk(addr) | 移動堆頂端 | 小塊分配(< 128KB,可調) |
mmap() | 匿名映射建立新 VMA | 大塊分配、非連續需求、M_MMAP_THRESHOLD |
munmap() | 釋放映射區域 | free 大塊內存 |
void *malloc(size_t size) {
// 1. 對齊、最小塊處理
size = align(size + SIZE_SZ);
// 2. 掃描 fastbin / smallbin
if (size <= MAX_FAST) {
chunk = fastbin_get(size);
if (chunk) return chunk2mem(chunk);
}
// 3. 掃描 smallbin / largebin / unsorted bin
chunk = bin_search(size);
if (chunk) return chunk2mem(chunk);
// 4. 向系統申請記憶體
if (size < MMAP_THRESHOLD) {
// 擴展堆
new_brk = sys_brk(current_brk + size + overhead);
chunk = create_chunk_at(old_brk, size);
} else {
// mmap 映射
chunk = sys_mmap(NULL, size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
}
// 5. 加入 bin、分割、返回
return chunk2mem(chunk);
}
munmap() 歸還內核brk() 縮減堆| 環境變數 | 默認值 | 作用 |
|---|---|---|
MALLOC_ARENA_MAX | CPU核數×8 | 限制 arena 數量,減少鎖爭用 |
M_MMAP_THRESHOLD | 128KB | 大於此值用 mmap |
M_TRIM_THRESHOLD | 128KB | 堆頂空閒超此值歸還內核 |
M_TOP_PAD | 0 | 擴展堆時額外預留 |
調用:mallopt(M_MMAP_THRESHOLD, 256*1024) 或環境變數預設。
valgrind --leak-check=full、mtrace()malloc_check_=3、glibc 內建檢查/proc/PID/smaps、mallinfo()perf record -g -- malloc、調整 arena 數jeprof, pprof)LD_PRELOAD=/usr/lib/libjemalloc.so