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