69天探索操作系统-第43天:内存碎片化

319 阅读5分钟
pro15.avif ## 1. 介绍

当内存被划分为小而分散的块时,就会发生内存碎片化,即使总空闲内存足够,也难以分配较大的内存块。碎片化会显著降低系统性能,导致内存利用率低下。

内存碎片化的关键概念

  • 内部碎片: 由于向上取整到最近的块大小,导致分配的内存块内存在浪费的空间。
  • 外部碎片: 在已分配的内存块之间的浪费空间,使得分配大连续块变得困难。
  • 内存紧凑化: 通过将已分配的块移动得更近来减少碎片的过程。
  • 分配策略: 在内存期间最小化碎片的技术。

2. 内存碎片类型

内存碎片化可以分为内部碎片和外部碎片。以下是内存管理器的实现,用于分析碎片化:

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

typedef struct MemoryBlock {
    size_t size;
    bool is_allocated;
    void *start_address;
    struct MemoryBlock *next;
    struct MemoryBlock *prev;
} MemoryBlock;

typedef struct {
    MemoryBlock *head;
    size_t total_size;
    size_t used_size;
    size_t internal_fragmentation;
    size_t external_fragmentation;
} MemoryManager;

void analyze_fragmentation(MemoryManager *manager) {
    MemoryBlock *current = manager->head;
    size_t total_internal = 0;
    size_t total_external = 0;
    size_t largest_free_block = 0;

    while (current != NULL) {
        if (current->is_allocated) {
            // Calculate internal fragmentation
            size_t block_internal = current->size -
                                  get_actual_data_size(current);
            total_internal += block_internal;
        } else {
            // Track external fragmentation
            total_external += current->size;
            if (current->size > largest_free_block) {
                largest_free_block = current->size;
            }
        }
        current = current->next;
    }

    manager->internal_fragmentation = total_internal;
    manager->external_fragmentation = total_external - largest_free_block;
}

3. 内存碎片整理算法

碎片整理涉及重新组织内存以减少碎片。以下是碎片整理算法的实现:

typedef struct {
    void *old_address;
    void *new_address;
    size_t size;
} RelocationEntry;

typedef struct {
    RelocationEntry *entries;
    size_t count;
    size_t capacity;
} RelocationTable;

bool defragment_memory(MemoryManager *manager) {
    RelocationTable relocation_table = {
        .entries = malloc(1000 * sizeof(RelocationEntry)),
        .count = 0,
        .capacity = 1000
    };

    // Phase 1: Analyze and plan relocations
    MemoryBlock *current = manager->head;
    void *next_free_address = manager->head->start_address;

    while (current != NULL) {
        if (current->is_allocated) {
            if (current->start_address != next_free_address) {
                // Need to relocate this block
                RelocationEntry entry = {
                    .old_address = current->start_address,
                    .new_address = next_free_address,
                    .size = current->size
                };
                relocation_table.entries[relocation_table.count++] = entry;
            }
            next_free_address += current->size;
        }
        current = current->next;
    }

    // Phase 2: Perform relocations
    for (size_t i = 0; i < relocation_table.count; i++) {
        RelocationEntry *entry = &relocation_table.entries[i];
        memmove(entry->new_address, entry->old_address, entry->size);
        update_pointers(manager, entry);
    }

    // Phase 3: Update memory block list
    coalesce_free_blocks(manager);

    free(relocation_table.entries);
    return true;
}

4. 内存压缩技术

内存紧凑化涉及将已分配的内存块移动以减少碎片。以下是内存紧凑化的实现:

typedef struct {
    void **pointers;
    size_t count;
} PointerRegistry;

bool compact_memory(MemoryManager *manager, PointerRegistry *registry) {
    // Phase 1: Mark all blocks
    mark_live_blocks(manager);

    // Phase 2: Calculate new addresses
    void *compact_address = manager->head->start_address;
    MemoryBlock *current = manager->head;

    while (current != NULL) {
        if (current->is_allocated) {
            current->new_address = compact_address;
            compact_address += current->size;
        }
        current = current->next;
    }

    // Phase 3: Update pointers
    for (size_t i = 0; i < registry->count; i++) {
        void *old_ptr = *registry->pointers[i];
        MemoryBlock *block = find_block_for_address(manager, old_ptr);
        if (block != NULL) {
            size_t offset = (char*)old_ptr - (char*)block->start_address;
            *registry->pointers[i] = (char*)block->new_address + offset;
        }
    }

    // Phase 4: Move memory
    current = manager->head;
    while (current != NULL) {
        if (current->is_allocated &&
            current->start_address != current->new_address) {
            memmove(current->new_address,
                   current->start_address,
                   current->size);
            current->start_address = current->new_address;
        }
        current = current->next;
    }

    return true;
}

5. 内存池管理

内存池分配固定大小的内存块,减少碎片。以下是内存池的实现:

typedef struct {
    void *pool_start;
    size_t block_size;
    size_t num_blocks;
    uint8_t *block_status;  // 0 = free, 1 = allocated
    void **free_blocks;
    size_t free_count;
} MemoryPool;

MemoryPool* create_memory_pool(size_t block_size, size_t num_blocks) {
    MemoryPool *pool = malloc(sizeof(MemoryPool));

    pool->block_size = block_size;
    pool->num_blocks = num_blocks;
    pool->pool_start = aligned_alloc(sizeof(void*),
                                   block_size * num_blocks);
    pool->block_status = calloc(num_blocks, sizeof(uint8_t));
    pool->free_blocks = malloc(num_blocks * sizeof(void*));
    pool->free_count = num_blocks;

    // Initialize free block list
    for (size_t i = 0; i < num_blocks; i++) {
        pool->free_blocks[i] = (char*)pool->pool_start +
                              (i * block_size);
    }

    return pool;
}

void* pool_allocate(MemoryPool *pool) {
    if (pool->free_count == 0) return NULL;

    void *block = pool->free_blocks[--pool->free_count];
    size_t block_index = ((char*)block - (char*)pool->pool_start) /
                        pool->block_size;
    pool->block_status[block_index] = 1;

    return block;
}

6. 高级内存分配策略

伙伴系统(buddy system) 是一种高级内存分配策略,通过分割和合并内存块来减少碎片。

伙伴系统实施

以下是伙伴系统的实现:

typedef struct {
    void *memory;
    size_t total_size;
    size_t min_block_size;
    size_t max_order;
    struct list_head *free_lists;
} BuddyAllocator;

BuddyAllocator* create_buddy_allocator(size_t total_size,
                                     size_t min_block_size) {
    BuddyAllocator *allocator = malloc(sizeof(BuddyAllocator));

    allocator->total_size = total_size;
    allocator->min_block_size = min_block_size;
    allocator->max_order = log2(total_size / min_block_size);
    allocator->memory = aligned_alloc(min_block_size, total_size);

    // Initialize free lists
    allocator->free_lists = malloc(sizeof(struct list_head) *
                                 (allocator->max_order + 1));
    for (size_t i = 0; i <= allocator->max_order; i++) {
        INIT_LIST_HEAD(&allocator->free_lists[i]);
    }

    // Add initial block to highest order free list
    add_to_free_list(allocator, allocator->memory, allocator->max_order);

    return allocator;
}

void* buddy_allocate(BuddyAllocator *allocator, size_t size) {
    size_t order = calculate_order(size, allocator->min_block_size);

    // Find suitable block
    for (size_t i = order; i <= allocator->max_order; i++) {
        if (!list_empty(&allocator->free_lists[i])) {
            void *block = remove_from_free_list(allocator, i);

            // Split block if necessary
            while (i > order) {
                i--;
                void *buddy = (char*)block + (1 << i);
                add_to_free_list(allocator, buddy, i);
            }

            return block;
        }
    }

    return NULL;
}

7. 防止碎片化

碎片预防涉及在内存分配过程中最小化碎片化的策略。

image.png

8. 监控和分析工具

监控工具有助于分析内存使用和碎片。以下是内存监控的实现:

typedef struct {
    size_t total_allocations;
    size_t total_deallocations;
    size_t peak_memory_usage;
    size_t current_memory_usage;
    double fragmentation_ratio;
    size_t largest_contiguous_free;
} MemoryStats;

void collect_memory_stats(MemoryManager *manager, MemoryStats *stats) {
    MemoryBlock *current = manager->head;
    size_t total_free = 0;
    size_t largest_free = 0;
    size_t current_free = 0;

    while (current != NULL) {
        if (current->is_allocated) {
            current_free = 0;
        } else {
            current_free += current->size;
            total_free += current->size;
            if (current_free > largest_free) {
                largest_free = current_free;
            }
        }
        current = current->next;
    }

    stats->largest_contiguous_free = largest_free;
    stats->fragmentation_ratio = 1.0 -
        ((double)largest_free / total_free);
}

9. 性能优化

内存碎片管理的关键性能考虑因素包括:

  • 分配时间复杂度: 池分配为O(1), 伙伴系统为O(log n)。
  • 内存开销: 用于跟踪碎片的额外结构。
  • 压缩成本: 完全压缩为O(n)。
  • 缓存性能: 内存布局对缓存效率的影响。

10. 总结

内存碎片管理对于系统性能和可靠性至关重要。了解并实施适当的碎片预防和管理技术可以显著提高系统效率和资源利用率。