內存池是為了解決大量malloc,free,導致的某些內存碎片。統(tǒng)一管理起來,比較方便。
基本思想是,根據(jù)要分配的內存,分為大塊內存和小塊內存。
小片內存(4k以內)節(jié)點,第一個成員last, 是當前節(jié)點的首地址,end是指該4k內存的最后一段地址。
struct mp_node_s{unsigned char *last; //當前節(jié)點的位置
unsigned char *end; //當前分配的內存(小于等于4k)最后一位
struct mp_node_s *next;//指向下一個節(jié)點
size_t failed=0;//失敗次數(shù)
};
大片內存:
struct mp_large_s{struct mp_large_s *next;//下個節(jié)點
void *alloc;//分配的內存
};
池節(jié)點:其其核心思想就是將分配的內存組織起來
struct mp_pool_s {struct mp_large_s *large;
struct mp_node_s *head;
struct mp_node_s *current; //指向當前的節(jié)點
int max;
};
創(chuàng)建池,先創(chuàng)建出一個32位對齊的內存塊,這個內存塊是size大小,再加上mp_pool_s這個結構體的本身大小.
#define MP_ALIGNMENT 32
#define MP_PAGE_SIZE 4096
#define MP_MAX_ALLOC_FROM_POOL (MP_PAGE_SIZE-1)
struct mp_pool_s *mp_create_pool(size_t size) {struct mp_pool_s *p;
int ret = posix_memalign((void **)&p, MP_ALIGNMENT, size + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s));
if (ret) {return NULL;
}
p->max = (size< MP_MAX_ALLOC_FROM_POOL) ? size : MP_MAX_ALLOC_FROM_POOL;//小與4k,就用原本的大小,大于4k,那么限制為4k-1
p->current = p->head; //將當前結點指向池的頭部
p->large = NULL;
p->head->last = (unsigned char *)p + sizeof(struct mp_pool_s) + sizeof(struct mp_node_s); //當前頭部
p->head->end = p->head->last + size;
p->head->failed = 0;
return p;
}
分配內存函數(shù),分為,①分配大塊內存; ②分配小內存節(jié)點時,考慮兩種情況,小內存塊還夠用,小內存塊不夠用了,得分配新的小內存塊。
void *mp_alloc(struct mp_pool_s *pool, size_t size) {unsigned char *m;
struct mp_node_s *p;
//小于等于小內存塊大小的
if (size<= pool->max) {//就在當前節(jié)點后分配內存
p = pool->current;
//遍歷當前節(jié)點后的節(jié)點,查找有沒有適合大小的內存塊
do {
m = mp_align_ptr(p->last, MP_ALIGNMENT);
//分配范圍,依然還在內存塊范圍的,就不新分配新塊了,就地分配
if ((size_t)(p->end - m) >= size) { p->last = m + size;
return m;
}
p = p->next;
} while (p);
//沒有合適大小的內存塊,直接創(chuàng)建一塊新小內存塊
return mp_alloc_block(pool, size);
}
//分配大塊內存
return mp_alloc_large(pool, size);
}
新建一個≤4k的小內存塊
#define mp_align(n, alignment) (((n)+(alignment-1)) & ~(alignment-1))
#define mp_align_ptr(p, alignment) (void *)((((size_t)p)+(alignment-1)) & ~(alignment-1))
static void *mp_alloc_block(struct mp_pool_s *pool, size_t size) {
unsigned char *m;//
struct mp_node_s *h = pool->head; //頭部的小內存節(jié)點
size_t psize = (size_t)(h->end - (unsigned char *)h); //獲取小內存塊大小
//為m分配出一個內存
int ret = posix_memalign((void **)&m, MP_ALIGNMENT, psize); //先分配出一個“頁”(<=4k)
if (ret) return NULL;
struct mp_node_s *p, *new_node, *current;
new_node = (struct mp_node_s*)m; //
new_node->end = m + psize;
new_node->next = NULL;
new_node->failed = 0;
//在分配好的小內存塊中,分配一塊節(jié)點內存size
m += sizeof(struct mp_node_s);
m = mp_align_ptr(m, MP_ALIGNMENT);
new_node->last = m + size; //last指向節(jié)點內存的末尾
current = pool->current;
//遍歷當前節(jié)點后的節(jié)點,如果有失敗大于4次的節(jié)點,就把池的當前節(jié)點指向失敗大于4次的節(jié)點
//4是一個經(jīng)驗值
for (p = current; p->next; p = p->next) {
if (p->failed++ >4) {
current = p->next;
}
}
p->next = new_node; //將最后一個結點的next指向新分配的內存塊
pool->current = current ? current : new_node;
return m;
}
```
創(chuàng)建大塊內存,非常好理解,一個單鏈表,沒什么好說的
static void *mp_alloc_large(struct mp_pool_s *pool, size_t size) {void *p = malloc(size); //直接分配內存
if (p == NULL) return NULL;
size_t n = 0;
struct mp_large_s *large;
for (large = pool->large; large; large = large->next) {if (large->alloc == NULL) { large->alloc = p;
return p;
}
if (n ++ >3) break;
}
//large結構體本身也是存在小內存塊里的
large = mp_alloc(pool, sizeof(struct mp_large_s));
if (large == NULL) {free(p);
return NULL;
}
large->alloc = p;
large->next = pool->large;
pool->large = large;
return p;
}
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)站標題:內存池的簡單實現(xiàn)c語言-創(chuàng)新互聯(lián)
瀏覽地址:http://www.rwnh.cn/article22/ccgjcc.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供營銷型網(wǎng)站建設、網(wǎng)站建設、網(wǎng)站排名、定制網(wǎng)站、建站公司、面包屑導航
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)