Linux内存管理机制深度解析

深入分析Linux内存管理架构,从虚拟内存到物理内存的映射机制,以及内存分配与回收的底层原理

Linux内存管理系统是操作系统最核心的组件之一,它负责管理物理内存、虚拟内存映射、内存分配与回收等关键功能。本文将深入解析Linux内存管理的工作原理,分析内存分配机制的性能特征,并提供相关的优化策略。

Linux内存管理架构

内存管理层次结构

Rendering diagram...

虚拟内存与物理内存

Linux采用虚拟内存管理机制,为每个进程提供独立的虚拟地址空间,通过页表实现虚拟地址到物理地址的映射。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>

// 查看进程内存映射
void show_memory_maps() {
    char command[256];
    snprintf(command,sizeof(command),"cat /proc/%d/maps",getpid());
    system(command);
}

// 虚拟内存地址分布测试
void virtual_memory_layout() {
    printf("虚拟内存地址分布测试\n");
    printf("=============================\n\n");
    
    // 代码段
    void *code_addr = (void *)virtual_memory_layout;
    printf("代码段地址: %p\n",code_addr);
    
    // 数据段
    static int global_var = 42;
    printf("全局变量地址: %p\n",&global_var);
    
    // 堆内存
    void *heap_addr = malloc(1024);
    printf("堆内存地址: %p\n",heap_addr);
    
    // 栈内存
    int stack_var;
    printf("栈内存地址: %p\n",&stack_var);
    
    // 内存映射区域
    void *mmap_addr = mmap(NULL,4096,PROT_READ | PROT_WRITE,
                        MAP_PRIVATE | MAP_ANONYMOUS,-1,0);
    printf("内存映射地址: %p\n",mmap_addr);
    
    // 库函数
    printf("库函数地址: %p\n",(void *)printf);
    
    // 地址空间布局
    printf("\n地址空间布局:\n");
    printf("  高地址: 内核空间\n");
    printf("  栈区: 向下增长\n");
    printf("  内存映射区: 共享库、mmap\n");
    printf("  堆区: 向上增长\n");
    printf("  BSS段: 未初始化数据\n");
    printf("  数据段: 已初始化数据\n");
    printf("  代码段: 只读代码\n");
    printf("  低地址: 保留区域\n");
    
    free(heap_addr);
    munmap(mmap_addr,4096);
}

// 页面大小测试
void test_page_size() {
    printf("\n页面大小信息\n");
    printf("=============================\n");
    printf("系统页面大小: %ld 字节\n",sysconf(_SC_PAGESIZE));
    
    // 使用mmap查看实际分配的页面
    void *addr1 = mmap(NULL,4096,PROT_READ | PROT_WRITE,
                   MAP_PRIVATE | MAP_ANONYMOUS,-1,0);
    void *addr2 = mmap(NULL,4096,PROT_READ | PROT_WRITE,
                   MAP_PRIVATE | MAP_ANONYMOUS,-1,0);
    
    printf("第一个mmap地址: %p\n",addr1);
    printf("第二个mmap地址: %p\n",addr2);
    printf("地址间距: %ld (应该是页面大小的倍数)\n",
        (char *)addr2 - (char *)addr1);
    
    munmap(addr1,4096);
    munmap(addr2,4096);
}

int main() {
    virtual_memory_layout();
    test_page_size();
    
    printf("\n当前进程内存映射:\n");
    printf("=============================\n");
    show_memory_maps();
    
    return 0;
}

内存分配机制

分配器层次结构

Rendering diagram...

伙伴系统实现

伙伴系统是Linux物理内存管理的核心,它将物理内存划分为大小为2^n的连续块。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#define MAX_ORDER 10  // 2^10 = 1024 页面
#define PAGE_SIZE 4096

// 伙伴系统页面块
typedef struct buddy_block {
    int order;
    bool free;
    struct buddy_block *next;
    struct buddy_block *prev;
} buddy_block;

// 伙伴系统管理器
typedef struct {
    buddy_block *free_lists[MAX_ORDER + 1];
    void *memory_start;
    size_t total_memory;
    size_t used_memory;
} buddy_system;

// 初始化伙伴系统
void buddy_init(buddy_system *bs,void *memory,size_t size) {
    memset(bs,0,sizeof(buddy_system));
    bs->memory_start = memory;
    bs->total_memory = size;
    
    // 将所有内存作为最大order的空闲块
    int max_order = 0;
    size_t temp_size = size / PAGE_SIZE;
    while (temp_size > 1) {
     temp_size >>= 1;
     max_order++;
    }
    
    if (max_order > MAX_ORDER) {
     max_order = MAX_ORDER;
    }
    
    buddy_block *block = (buddy_block *)memory;
    block->order = max_order;
    block->free = true;
    block->next = NULL;
    block->prev = NULL;
    
    bs->free_lists[max_order] = block;
}

// 查找伙伴块
buddy_block* buddy_find_buddy(buddy_system *bs,buddy_block *block) {
    size_t offset = (size_t)block - (size_t)bs->memory_start;
    size_t buddy_offset = offset ^ (1 << block->order);
    
    if (buddy_offset >= bs->total_memory) {
     return NULL;
    }
    
    buddy_block *buddy = (buddy_block *)((char *)bs->memory_start + buddy_offset);
    
    if (buddy->order != block->order || !buddy->free) {
     return NULL;
    }
    
    return buddy;
}

// 从空闲列表中移除块
void remove_from_list(buddy_block **list,buddy_block *block) {
    if (block->prev) {
     block->prev->next = block->next;
    } else {
     *list = block->next;
    }
    
    if (block->next) {
     block->next->prev = block->prev;
    }
    
    block->next = block->prev = NULL;
}

// 添加到空闲列表
void add_to_list(buddy_block **list,buddy_block *block) {
    block->next = *list;
    block->prev = NULL;
    
    if (*list) {
     (*list)->prev = block;
    }
    
    *list = block;
}

// 分配内存块
void* buddy_alloc(buddy_system *bs,int order) {
    if (order < 0 || order > MAX_ORDER) {
     return NULL;
    }
    
    // 查找合适大小的空闲块
    int current_order = order;
    while (current_order <= MAX_ORDER && !bs->free_lists[current_order]) {
     current_order++;
    }
    
    if (current_order > MAX_ORDER) {
     return NULL;  // 内存不足
    }
    
    // 从空闲列表中取出块
    buddy_block *block = bs->free_lists[current_order];
    remove_from_list(&bs->free_lists[current_order],block);
    
    // 如果块太大,分裂它
    while (current_order > order) {
     current_order--;
     
     buddy_block *buddy = (buddy_block *)((char *)block + (1 << current_order) * PAGE_SIZE);
     buddy->order = current_order;
     buddy->free = true;
     buddy->next = buddy->prev = NULL;
     
     add_to_list(&bs->free_lists[current_order],buddy);
    }
    
    block->order = order;
    block->free = false;
    bs->used_memory += (1 << order) * PAGE_SIZE;
    
    return block;
}

// 释放内存块
void buddy_free(buddy_system *bs,void *ptr,int order) {
    buddy_block *block = (buddy_block *)ptr;
    block->order = order;
    block->free = false;
    
    bs->used_memory -= (1 << order) * PAGE_SIZE;
    
    // 尝试与伙伴合并
    while (order < MAX_ORDER) {
     buddy_block *buddy = buddy_find_buddy(bs,block);
     
     if (!buddy) {
         break;
     }
     
     // 从空闲列表中移除伙伴
     remove_from_list(&bs->free_lists[order],buddy);
     
     // 合并两个块
     if (block > buddy) {
         block = buddy;
     }
     
     block->order = ++order;
    }
    
    block->free = true;
    add_to_list(&bs->free_lists[block->order],block);
}

// 打印内存使用情况
void buddy_print_stats(buddy_system *bs) {
    printf("内存使用统计:\n");
    printf("  总内存: %zu 字节\n",bs->total_memory);
    printf("  已使用: %zu 字节\n",bs->used_memory);
    printf("  空闲内存: %zu 字节\n",bs->total_memory - bs->used_memory);
    printf("  使用率: %.2f%%\n",
        (double)bs->used_memory / bs->total_memory * 100);
    
    printf("\n空闲块统计:\n");
    for (int i = 0; i <= MAX_ORDER; i++) {
     int count = 0;
     buddy_block *block = bs->free_lists[i];
     while (block) {
         count++;
         block = block->next;
     }
     
     if (count > 0) {
         printf("  Order %d (大小: %zu 页面): %d 个空闲块\n",
                i,(size_t)1 << i,count);
     }
    }
}

// 伙伴系统测试
void test_buddy_system() {
    printf("伙伴系统测试\n");
    printf("=============================\n\n");
    
    // 分配内存池 (1MB)
    size_t pool_size = 1024 * 1024;
    void *memory_pool = malloc(pool_size);
    
    buddy_system bs;
    buddy_init(&bs,memory_pool,pool_size);
    
    buddy_print_stats(&bs);
    
    // 分配测试
    printf("\n分配测试:\n");
    void *block1 = buddy_alloc(&bs,0);  // 1 页面
    void *block2 = buddy_alloc(&bs,2);  // 4 页面
    void *block3 = buddy_alloc(&bs,1);  // 2 页面
    void *block4 = buddy_alloc(&bs,3);  // 8 页面
    
    printf("分配的块:\n");
    printf("  块1: %p (1 页面)\n",block1);
    printf("  块2: %p (4 页面)\n",block2);
    printf("  块3: %p (2 页面)\n",block3);
    printf("  块4: %p (8 页面)\n",block4);
    
    buddy_print_stats(&bs);
    
    // 释放测试
    printf("\n释放测试:\n");
    buddy_free(&bs,block2,2);
    printf("释放块2后:\n");
    buddy_print_stats(&bs);
    
    buddy_free(&bs,block1,0);
    printf("释放块1后:\n");
    buddy_print_stats(&bs);
    
    // 释放所有内存
    buddy_free(&bs,block3,1);
    buddy_free(&bs,block4,3);
    
    printf("\n释放所有内存后:\n");
    buddy_print_stats(&bs);
    
    free(memory_pool);
}

int main() {
    test_buddy_system();
    return 0;
}

Slab分配器原理

Slab分配器是建立在伙伴系统之上的高级内存分配器,专门用于内核对象的频繁分配和释放。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define OBJECT_SIZE 64
#define OBJECTS_PER_SLAB 16

// Slab对象
typedef struct slab_object {
    void *data;
    struct slab_object *next;
} slab_object;

// Slab描述符
typedef struct slab {
    void *memory;
    slab_object *free_objects;
    int inuse;
    struct slab *next;
    struct slab *prev;
} slab;

// Slab缓存
typedef struct slab_cache {
    char name[32];
    size_t object_size;
    int objects_per_slab;
    slab *full_slabs;      // 完全使用的slab
    slab *partial_slabs;   // 部分使用的slab
    slab *empty_slabs;     // 完全空闲的slab
    int total_objects;
    int free_objects;
} slab_cache;

// 创建新slab
slab* create_slab(slab_cache *cache) {
    slab *s = malloc(sizeof(slab));
    if (!s) return NULL;
    
    // 分配slab内存
    size_t slab_size = cache->object_size * cache->objects_per_slab;
    s->memory = malloc(slab_size);
    if (!s->memory) {
     free(s);
     return NULL;
    }
    
    // 初始化空闲对象链表
    s->free_objects = NULL;
    s->inuse = 0;
    s->next = s->prev = NULL;
    
    // 将slab中的对象添加到空闲链表
    for (int i = cache->objects_per_slab - 1; i >= 0; i--) {
     slab_object *obj = malloc(sizeof(slab_object));
     obj->data = (char *)s->memory + i * cache->object_size;
     obj->next = s->free_objects;
     s->free_objects = obj;
    }
    
    cache->total_objects += cache->objects_per_slab;
    cache->free_objects += cache->objects_per_slab;
    
    return s;
}

// 初始化slab缓存
void slab_cache_init(slab_cache *cache,const char *name,size_t object_size,int objects_per_slab) {
    strncpy(cache->name,name,sizeof(cache->name) - 1);
    cache->object_size = object_size;
    cache->objects_per_slab = objects_per_slab;
    cache->full_slabs = NULL;
    cache->partial_slabs = NULL;
    cache->empty_slabs = NULL;
    cache->total_objects = 0;
    cache->free_objects = 0;
}

// 从slab缓存分配对象
void* slab_alloc(slab_cache *cache) {
    slab *s;
    
    // 优先从部分使用的slab分配
    if (cache->partial_slabs) {
     s = cache->partial_slabs;
    } else if (cache->empty_slabs) {
     s = cache->empty_slabs;
     // 移动到部分使用列表
     if (s->prev) s->prev->next = s->next;
     else cache->empty_slabs = s->next;
     
     if (s->next) s->next->prev = s->prev;
     
     s->next = cache->partial_slabs;
     s->prev = NULL;
     if (cache->partial_slabs) cache->partial_slabs->prev = s;
     cache->partial_slabs = s;
    } else {
     // 创建新slab
     s = create_slab(cache);
     if (!s) return NULL;
     
     s->next = cache->partial_slabs;
     cache->partial_slabs = s;
    }
    
    // 从slab中分配对象
    if (!s->free_objects) {
     return NULL;  // 不应该发生
    }
    
    slab_object *obj = s->free_objects;
    s->free_objects = obj->next;
    s->inuse++;
    cache->free_objects--;
    
    // 检查slab是否已满
    if (s->inuse == cache->objects_per_slab) {
     // 移动到满slab列表
     if (s->prev) s->prev->next = s->next;
     else cache->partial_slabs = s->next;
     
     if (s->next) s->next->prev = s->prev;
     
     s->next = cache->full_slabs;
     s->prev = NULL;
     if (cache->full_slabs) cache->full_slabs->prev = s;
     cache->full_slabs = s;
    }
    
    void *data = obj->data;
    free(obj);
    return data;
}

// 释放对象到slab缓存
void slab_free(slab_cache *cache,void *obj) {
    // 查找对象所在的slab
    slab *s = cache->full_slabs;
    while (s) {
     if ((char *)obj >= (char *)s->memory && 
         (char *)obj < (char *)s->memory + 
                        cache->object_size * cache->objects_per_slab) {
         break;
     }
     s = s->next;
    }
    
    if (!s) {
     s = cache->partial_slabs;
     while (s) {
         if ((char *)obj >= (char *)s->memory && 
             (char *)obj < (char *)s->memory + 
                            cache->object_size * cache->objects_per_slab) {
             break;
         }
         s = s->next;
     }
    }
    
    if (!s) {
     printf("错误: 对象不属于任何slab\n");
     return;
    }
    
    // 如果slab是满的,移动到部分使用列表
    if (s->inuse == cache->objects_per_slab) {
     if (s->prev) s->prev->next = s->next;
     else cache->full_slabs = s->next;
     
     if (s->next) s->next->prev = s->prev;
     
     s->next = cache->partial_slabs;
     s->prev = NULL;
     if (cache->partial_slabs) cache->partial_slabs->prev = s;
     cache->partial_slabs = s;
    }
    
    // 将对象添加回空闲链表
    slab_object *new_obj = malloc(sizeof(slab_object));
    new_obj->data = obj;
    new_obj->next = s->free_objects;
    s->free_objects = new_obj;
    
    s->inuse--;
    cache->free_objects++;
    
    // 如果slab变为空闲,移动到空闲slab列表
    if (s->inuse == 0) {
     if (s->prev) s->prev->next = s->next;
     else cache->partial_slabs = s->next;
     
     if (s->next) s->next->prev = s->prev;
     
     s->next = cache->empty_slabs;
     s->prev = NULL;
     if (cache->empty_slabs) cache->empty_slabs->prev = s;
     cache->empty_slabs = s;
    }
}

// 打印slab缓存统计信息
void slab_cache_print_stats(slab_cache *cache) {
    printf("Slab缓存 '%s' 统计:\n",cache->name);
    printf("  对象大小: %zu 字节\n",cache->object_size);
    printf("  每个slab对象数: %d\n",cache->objects_per_slab);
    printf("  总对象数: %d\n",cache->total_objects);
    printf("  空闲对象数: %d\n",cache->free_objects);
    printf("  使用对象数: %d\n",cache->total_objects - cache->free_objects);
    printf("  使用率: %.2f%%\n",
        (double)(cache->total_objects - cache->free_objects) / 
        cache->total_objects * 100);
    
    printf("  Slab状态:\n");
    printf("    满slab数: ");
    int full_count = 0;
    slab *s = cache->full_slabs;
    while (s) { full_count++; s = s->next; }
    printf("%d\n",full_count);
    
    printf("    部分使用slab数: ");
    int partial_count = 0;
    s = cache->partial_slabs;
    while (s) { partial_count++; s = s->next; }
    printf("%d\n",partial_count);
    
    printf("    空闲slab数: ");
    int empty_count = 0;
    s = cache->empty_slabs;
    while (s) { empty_count++; s = s->next; }
    printf("%d\n",empty_count);
}

// Slab分配器测试
void test_slab_allocator() {
    printf("Slab分配器测试\n");
    printf("=============================\n\n");
    
    slab_cache cache;
    slab_cache_init(&cache,"test_cache",OBJECT_SIZE,OBJECTS_PER_SLAB);
    
    slab_cache_print_stats(&cache);
    
    // 分配测试
    printf("\n分配测试:\n");
    void *objects[20];
    for (int i = 0; i < 20; i++) {
     objects[i] = slab_alloc(&cache);
     if (objects[i]) {
         printf("  分配对象 %d: %p\n",i,objects[i]);
     } else {
         printf("  分配对象 %d: 失败\n",i);
     }
    }
    
    slab_cache_print_stats(&cache);
    
    // 释放测试
    printf("\n释放测试:\n");
    for (int i = 0; i < 10; i++) {
     slab_free(&cache,objects[i]);
     printf("  释放对象 %d\n",i);
    }
    
    slab_cache_print_stats(&cache);
    
    // 释放剩余对象
    printf("\n释放剩余对象:\n");
    for (int i = 10; i < 20; i++) {
     slab_free(&cache,objects[i]);
    }
    
    slab_cache_print_stats(&cache);
}

int main() {
    test_slab_allocator();
    return 0;
}

内存分配性能分析

分配器性能对比

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>

// 性能测试宏
#define BENCHMARK(name,func,iterations) \
    do { \
     struct timeval start,end; \
     gettimeofday(&start,NULL); \
     for (int i = 0; i < iterations; i++) { \
         func; \
     } \
     gettimeofday(&end,NULL); \
     double elapsed = (end.tv_sec - start.tv_sec) + \
                     (end.tv_usec - start.tv_usec) / 1000000.0; \
     printf("%s: %.4f 秒 (%.2f ops/sec)\n",\
            name,elapsed,iterations / elapsed); \
    } while(0)

// 小内存分配测试
void test_small_allocations() {
    printf("小内存分配性能测试 (100字节)\n");
    printf("=============================\n");
    
    const int iterations = 1000000;
    
    BENCHMARK("malloc",{
     void *ptr = malloc(100);
     free(ptr);
    },iterations);
    
    BENCHMARK("calloc",{
     void *ptr = calloc(1,100);
     free(ptr);
    },iterations);
}

// 大内存分配测试
void test_large_allocations() {
    printf("\n大内存分配性能测试 (1MB)\n");
    printf("=============================\n");
    
    const int iterations = 10000;
    
    BENCHMARK("malloc",{
     void *ptr = malloc(1024 * 1024);
     free(ptr);
    },iterations);
}

// 内存模式测试
void test_allocation_patterns() {
    printf("\n内存分配模式测试\n");
    printf("=============================\n");
    
    const int iterations = 100000;
    
    // 随机大小分配
    printf("随机大小分配 (16-1024 字节):\n");
    BENCHMARK("random malloc",{
     size_t size = (rand() % 64 + 1) * 16;
     void *ptr = malloc(size);
     memset(ptr,0,size);
     free(ptr);
    },iterations);
    
    // 固定大小重复分配
    printf("固定大小重复分配 (256 字节):\n");
    BENCHMARK("fixed malloc",{
     void *ptr = malloc(256);
     free(ptr);
    },iterations);
    
    // 分配后延迟释放
    printf("分配后延迟释放 (1000 个对象):\n");
    void *ptrs[1000];
    for (int i = 0; i < 1000; i++) {
     ptrs[i] = malloc(256);
    }
    struct timeval start,end;
    gettimeofday(&start,NULL);
    for (int iter = 0; iter < iterations / 1000; iter++) {
     for (int i = 0; i < 1000; i++) {
         free(ptrs[i]);
         ptrs[i] = malloc(256);
     }
    }
    gettimeofday(&end,NULL);
    for (int i = 0; i < 1000; i++) {
     free(ptrs[i]);
    }
    double elapsed = (end.tv_sec - start.tv_sec) + 
                 (end.tv_usec - start.tv_usec) / 1000000.0;
    printf("  %.4f 秒 (%.2f ops/sec)\n",elapsed,iterations / elapsed);
}

// 内存碎片测试
void test_memory_fragmentation() {
    printf("\n内存碎片测试\n");
    printf("=============================\n");
    
    const int num_allocations = 10000;
    void *ptrs[num_allocations];
    
    // 分配大量小对象
    printf("分配 %d 个小对象 (随机大小 16-512 字节)...\n",num_allocations);
    for (int i = 0; i < num_allocations; i++) {
     size_t size = (rand() % 32 + 1) * 16;
     ptrs[i] = malloc(size);
     if (!ptrs[i]) {
         printf("分配失败在 %d\n",i);
         break;
     }
    }
    
    // 随机释放一半
    printf("随机释放一半对象...\n");
    for (int i = 0; i < num_allocations; i++) {
     if (rand() % 2 == 0) {
         free(ptrs[i]);
         ptrs[i] = NULL;
     }
    }
    
    // 尝试分配大块内存
    printf("尝试分配大块内存 (1MB)...\n");
    void *large_block = malloc(1024 * 1024);
    if (large_block) {
     printf("  成功分配 1MB\n");
     free(large_block);
    } else {
     printf("  分配失败\n");
    }
    
    // 释放剩余内存
    printf("释放剩余内存...\n");
    for (int i = 0; i < num_allocations; i++) {
     if (ptrs[i]) {
         free(ptrs[i]);
     }
    }
}

int main() {
    test_small_allocations();
    test_large_allocations();
    test_allocation_patterns();
    test_memory_fragmentation();
    
    return 0;
}

内存回收与交换

页面回收机制

Linux采用复杂的页面回收机制来管理内存压力,包括LRU算法、页面换出、交换等。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LRU_LIST_SIZE 100

// 页面描述符
typedef struct page {
    unsigned long address;
    int ref_count;
    int age;  // 用于LRU算法
    struct page *next;
    struct page *prev;
} page;

// LRU页面列表
typedef struct {
    page *head;
    page *tail;
    int size;
    int max_size;
} lru_list;

// 初始化LRU列表
void lru_init(lru_list *list,int max_size) {
    list->head = list->tail = NULL;
    list->size = 0;
    list->max_size = max_size;
}

// 添加页面到LRU列表头部
void lru_add(lru_list *list,page *p) {
    p->next = list->head;
    p->prev = NULL;
    
    if (list->head) {
     list->head->prev = p;
    } else {
     list->tail = p;
    }
    
    list->head = p;
    list->size++;
}

// 从LRU列表中移除页面
void lru_remove(lru_list *list,page *p) {
    if (p->prev) {
     p->prev->next = p->next;
    } else {
     list->head = p->next;
    }
    
    if (p->next) {
     p->next->prev = p->prev;
    } else {
     list->tail = p->prev;
    }
    
    p->next = p->prev = NULL;
    list->size--;
}

// 访问页面(更新LRU)
void lru_access(lru_list *list,page *p) {
    lru_remove(list,p);
    lru_add(list,p);
    p->age++;  // 增加页面年龄
}

// 获取最久未使用的页面
page* lru_get_victim(lru_list *list) {
    return list->tail;
}

// 模拟页面回收
void simulate_page_reclaim() {
    printf("页面回收模拟\n");
    printf("=============================\n\n");
    
    lru_list active_list,inactive_list;
    lru_init(&active_list,LRU_LIST_SIZE);
    lru_init(&inactive_list,LRU_LIST_SIZE);
    
    // 创建页面
    page pages[20];
    for (int i = 0; i < 20; i++) {
     pages[i].address = i * 4096;
     pages[i].ref_count = 0;
     pages[i].age = 0;
     pages[i].next = pages[i].prev = NULL;
    }
    
    // 初始加载页面到活跃列表
    printf("初始加载页面到活跃列表:\n");
    for (int i = 0; i < 10; i++) {
     lru_add(&active_list,&pages[i]);
     printf("  页面 %ld 加入活跃列表\n",pages[i].address / 4096);
    }
    
    // 模拟页面访问
    printf("\n模拟页面访问模式:\n");
    int access_pattern[] = {0,1,2,10,11,0,3,4,12,1,2,5,13,0,1};
    for (int i = 0; i < 15; i++) {
     int page_idx = access_pattern[i];
     
     // 检查页面是否在活跃列表中
     page *p = &pages[page_idx];
     if (p->age > 0) {  // 页面已经在列表中
         printf("  访问页面 %ld (已加载)\n",p->address / 4096);
         lru_access(&active_list,p);
     } else {  // 新页面,需要加载
         printf("  访问页面 %ld (缺页,需要加载)\n",p->address / 4096);
         
         // 如果活跃列表满了,移动旧页面到不活跃列表
         if (active_list.size >= active_list.max_size) {
             page *old_page = lru_get_victim(&active_list);
             printf("    移动页面 %ld 到不活跃列表\n",
                    old_page->address / 4096);
             lru_remove(&active_list,old_page);
             
             // 如果不活跃列表也满了,回收页面
             if (inactive_list.size >= inactive_list.max_size) {
                 page *reclaim_page = lru_get_victim(&inactive_list);
                 printf("    回收页面 %ld\n",
                        reclaim_page->address / 4096);
                 lru_remove(&inactive_list,reclaim_page);
                 reclaim_page->age = 0;  // 重置页面
             }
             
             lru_add(&inactive_list,old_page);
         }
         
         lru_add(&active_list,p);
     }
    }
    
    printf("\n最终状态:\n");
    printf("  活跃列表: %d 个页面\n",active_list.size);
    printf("  不活跃列表: %d 个页面\n",inactive_list.size);
}

// 交换机制模拟
void simulate_swapping() {
    printf("\n交换机制模拟\n");
    printf("=============================\n");
    
    printf("交换策略:\n");
    printf("  1. 当内存压力高时,启动页面回收\n");
    printf("  2. 优先回收不活跃的干净页面\n");
    printf("  3. 脏页面需要先写回磁盘\n");
    printf("  4. 如果页面可交换,移动到交换空间\n");
    printf("  5. 访问交换出的页面时触发缺页异常\n");
    printf("  6. 从交换空间读回页面到内存\n");
    
    printf("\n交换优化:\n");
    printf("  - 使用快速SSD作为交换设备\n");
    printf("  - 调整swappiness参数控制交换倾向\n");
    printf("  - 使用zswap压缩交换页面\n");
    printf("  - 避免关键进程的内存被交换\n");
}

int main() {
    simulate_page_reclaim();
    simulate_swapping();
    
    return 0;
}

内存监控与调优

# 内存使用监控
free -h
cat /proc/meminfo
vmstat -s

# 页面回收统计
cat /proc/vmstat | grep -E '(pgpgin|pgpgout|pswpin|pswpout)'
cat /proc/vmstat | grep numa_

# 交换使用情况
swapon -s
cat /proc/swaps

# 内存压力测试
stress --vm 1 --vm-bytes 1G --timeout 60s

# 调整交换参数
echo 10 > /proc/sys/vm/swappiness
echo 1 > /proc/sys/vm/vfs_cache_pressure

# 查看OOM killer日志
dmesg | grep -i "killed process"
journalctl | grep -i "out of memory"

# 内存映射查看
pmap <pid>
cat /proc/<pid>/maps
cat /proc/<pid>/smaps

Linux内存管理是一个复杂而精密的系统,通过虚拟内存机制、多级分配器和智能的回收策略,实现了高效的内存利用和性能优化。深入理解这些机制对于系统性能调优和问题诊断具有重要意义。