先阅读以下代码
c#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define POOL_SIZE 1024 // 内存池大小
#define BLOCK_SIZE 1024 // 每个内存块的大小
typedef struct MemoryBlock {
struct MemoryBlock* next;
} MemoryBlock;
typedef struct MemoryPool {
MemoryBlock* freeList; // 空闲内存块链表
char* memory; // 内存池的实际内存
pthread_mutex_t lock; // 互斥锁,用于线程安全
} MemoryPool;
MemoryPool* createMemoryPool() {
MemoryPool* pool = (MemoryPool*)malloc(sizeof(MemoryPool));
if (!pool) return NULL;
pool->memory = (char*)malloc(POOL_SIZE * BLOCK_SIZE);
if (!pool->memory) {
free(pool);
return NULL;
}
pool->freeList = NULL;
for (int i = 0; i < POOL_SIZE; i++) {
MemoryBlock* block = (MemoryBlock*)(pool->memory + i * BLOCK_SIZE);
block->next = pool->freeList;
pool->freeList = block;
}
pthread_mutex_init(&pool->lock, NULL);
return pool;
}
void* allocateFromPool(MemoryPool* pool) {
pthread_mutex_lock(&pool->lock);
if (!pool->freeList) {
pthread_mutex_unlock(&pool->lock);
return NULL; // 内存池已满
}
MemoryBlock* block = pool->freeList;
pool->freeList = block->next;
pthread_mutex_unlock(&pool->lock);
return (void*)block;
}
void freeToPool(MemoryPool* pool, void* ptr) {
if (!ptr) return;
pthread_mutex_lock(&pool->lock);
MemoryBlock* block = (MemoryBlock*)ptr;
block->next = pool->freeList;
pool->freeList = block;
pthread_mutex_unlock(&pool->lock);
}
void destroyMemoryPool(MemoryPool* pool) {
if (!pool) return;
pthread_mutex_destroy(&pool->lock);
free(pool->memory);
free(pool);
}
int main() {
MemoryPool* pool = createMemoryPool();
if (!pool) {
printf("Failed to create memory pool\n");
return 1;
}
void* ptr1 = allocateFromPool(pool);
void* ptr2 = allocateFromPool(pool);
if (ptr1 && ptr2) {
printf("Allocated memory blocks: %p, %p\n", ptr1, ptr2);
}
freeToPool(pool, ptr1);
freeToPool(pool, ptr2);
destroyMemoryPool(pool);
return 0;
}
以下为解析
这个内存池使用了互斥锁来确保线程安全。
c#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define POOL_SIZE 1024 // 内存池大小
#define BLOCK_SIZE 64 // 每个内存块的大小
typedef struct MemoryBlock {
struct MemoryBlock* next;
} MemoryBlock;
typedef struct MemoryPool {
MemoryBlock* freeList; // 空闲内存块链表
char* memory; // 内存池的实际内存
pthread_mutex_t lock; // 互斥锁,用于线程安全
} MemoryPool;
cMemoryPool* createMemoryPool() {
MemoryPool* pool = (MemoryPool*)malloc(sizeof(MemoryPool));
if (!pool) return NULL;
pool->memory = (char*)malloc(POOL_SIZE * BLOCK_SIZE);
if (!pool->memory) {
free(pool);
return NULL;
}
pool->freeList = NULL;
for (int i = 0; i < POOL_SIZE; i++) {
MemoryBlock* block = (MemoryBlock*)(pool->memory + i * BLOCK_SIZE);
block->next = pool->freeList;
pool->freeList = block;
}
pthread_mutex_init(&pool->lock, NULL);
return pool;
}
cvoid* allocateFromPool(MemoryPool* pool) {
pthread_mutex_lock(&pool->lock);
if (!pool->freeList) {
pthread_mutex_unlock(&pool->lock);
return NULL; // 内存池已满
}
MemoryBlock* block = pool->freeList;
pool->freeList = block->next;
pthread_mutex_unlock(&pool->lock);
return (void*)block;
}
cvoid freeToPool(MemoryPool* pool, void* ptr) {
if (!ptr) return;
pthread_mutex_lock(&pool->lock);
MemoryBlock* block = (MemoryBlock*)ptr;
block->next = pool->freeList;
pool->freeList = block;
pthread_mutex_unlock(&pool->lock);
}
cvoid destroyMemoryPool(MemoryPool* pool) {
if (!pool) return;
pthread_mutex_destroy(&pool->lock);
free(pool->memory);
free(pool);
}
cint main() {
MemoryPool* pool = createMemoryPool();
if (!pool) {
printf("Failed to create memory pool\n");
return 1;
}
void* ptr1 = allocateFromPool(pool);
void* ptr2 = allocateFromPool(pool);
if (ptr1 && ptr2) {
printf("Allocated memory blocks: %p, %p\n", ptr1, ptr2);
}
freeToPool(pool, ptr1);
freeToPool(pool, ptr2);
destroyMemoryPool(pool);
return 0;
}
freeList,实际内存 memory,以及一个互斥锁 lock。NULL。通过使用 pthread_mutex_lock 和 pthread_mutex_unlock,确保了在多线程环境下对内存池的操作是线程安全的。
这段代码的作用是将内存池中的内存块初始化为一个空闲链表。让我们逐步分析这段代码,帮助你更好地理解。
cfor (int i = 0; i < POOL_SIZE; i++) {
MemoryBlock* block = (MemoryBlock*)(pool->memory + i * BLOCK_SIZE);
block->next = pool->freeList;
pool->freeList = block;
}
pool->memory:
pool->memory 是内存池的实际内存区域,它是一个连续的内存块,大小为 POOL_SIZE * BLOCK_SIZE。POOL_SIZE 个小的内存块,每个内存块的大小为 BLOCK_SIZE。MemoryBlock* block = (MemoryBlock*)(pool->memory + i * BLOCK_SIZE):
pool->memory + i * BLOCK_SIZE,我们计算第 i 个内存块的起始地址。MemoryBlock* 类型,表示一个内存块。block->next = pool->freeList:
block->next 是当前内存块的 next 指针,指向下一个空闲内存块。block->next 指向当前的空闲链表头 pool->freeList。pool->freeList = block:
block 设置为新的空闲链表头。假设 POOL_SIZE = 3,BLOCK_SIZE = 64,内存池的内存布局如下:
内存池地址范围:0x1000 - 0x11C0 内存块 0:0x1000 - 0x1040 内存块 1:0x1040 - 0x1080 内存块 2:0x1080 - 0x10C0
block = (MemoryBlock*)(0x1000 + 0 * 64) = 0x1000block->next = pool->freeList(初始时 pool->freeList 为 NULL)pool->freeList = block(pool->freeList 现在指向 0x1000)空闲链表:0x1000 -> NULL
block = (MemoryBlock*)(0x1000 + 1 * 64) = 0x1040block->next = pool->freeList(pool->freeList 当前指向 0x1000)pool->freeList = block(pool->freeList 现在指向 0x1040)空闲链表:0x1040 -> 0x1000 -> NULL
block = (MemoryBlock*)(0x1000 + 2 * 64) = 0x1080block->next = pool->freeList(pool->freeList 当前指向 0x1040)pool->freeList = block(pool->freeList 现在指向 0x1080)空闲链表:0x1080 -> 0x1040 -> 0x1000 -> NULL
经过循环后,空闲链表 pool->freeList 指向最后一个内存块 0x1080,链表的结构如下:
0x1080 -> 0x1040 -> 0x1000 -> NULL
这样,内存池中的所有内存块都被链接在一起,形成一个空闲链表。当需要分配内存时,可以从链表的头部取出一个内存块;当释放内存时,可以将内存块重新插入链表的头部。
使用链表的好处是:
本文作者:Ryohei010
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!