重复造轮子系列--内存池(C语言)
这个代码是我上个公司工作项目的里面内存管理(基于伙伴算法)的一个简化又简化的版本。
因为没有内存边界检查;
因为没有内存使用统计;
因为没有考虑线程安全;
因为没有内存分配操作的具体文件位置信息;
因为没有考虑内存的浪费;
因为特别简单。。。所以也有一些用处,我定义了最小的内存为8字节,因此可以将任意内存大小散列到8的倍数之内,对于64位的通信系统来说,字节对齐是非常重要的;
mem_pool.h
#ifndef MEM_POOL_H_
#define MEM_POOL_H_ typedef struct MemBlock {
struct MemBlock* next;
int size;
void *ptr;
} MemBlock; typedef unsigned char byte; // 8 16 32 64 128 256 512 1024 2048 4096
// 1 2 4 8 16 32 64 128 256 512
// 0 1 2 3 4 5 6 7 8 9 #define MEM_POOL_MAX 10
#define MEM_BLOCK 8
#define MEM_BLOCK_BASE 8192
#define MEM_BLOCK_TYPE_NUM 10
#define MEM_BLOCK_FREE -1 int mem_pool_index(size_t size);
void mem_pool_init();
void mem_pool_free();
int mem_block_num(size_t size);
MemBlock* mem_block_head_get(size_t size);
void* mem_get(size_t size);
int mem_free(void **ptr); #define mem_ret(ptr) mem_free((void **)&ptr) ////////////////////////////////////////////////////////////////////////// typedef struct MemBlockDlist {
struct MemBlockDlist* prev;
struct MemBlockDlist* next;
int size;
void *ptr;
} MemBlockDlist; void mem_pool_dlist_init();
void mem_pool_dlist_free();
void* mem_realloc(size_t size);
void mem_release(void** ptr); #define mem_alloc(s) mem_realloc(s)
#define mem_relex(p) mem_release((void **)&p) #endif
mem_pool.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "mem_pool.h" static byte* g_pool_mem[MEM_POOL_MAX] = {};
static MemBlock* g_pool[MEM_POOL_MAX] = {};
const float log2 = log(2.0);
int mem_pool_index(size_t size) {
if (size > && size <= MEM_BLOCK) return ; size_t s = ;
size_t t = size;
size_t i; i = log((float)t)/log2;
17 s = s<<i;
return s == size ? i- : i-;
} MemBlock* mem_block_head(size_t index) {
if (index < || index >= MEM_POOL_MAX)
return NULL; return g_pool[index];
} MemBlock* mem_block_head_get(size_t size) {
if (size > MEM_BLOCK_BASE/ || size <= ) {
printf("size=%d too big to mem pool. using malloc plz\n", size);
return NULL;
}
return mem_block_head(mem_pool_index(size));
} int mem_block_num(size_t size) {
return MEM_BLOCK_BASE/size;// size > 0 is true
} static MemBlock* mem_block_alloc(byte* buf, int block_size, int block_num) {
MemBlock *head, *curr, *next;
int i; head = (MemBlock *)buf;
head->size = MEM_BLOCK_FREE;
head->ptr = (byte*)head + sizeof(MemBlock);
head->next = NULL; curr = head;
for (i=; i<block_num; i++) {
next = (MemBlock*)((byte*)curr + block_size);
next->size = MEM_BLOCK_FREE;
next->ptr = (byte*)next + sizeof(MemBlock);
curr->next = next;
next->next = NULL;
curr = next;
}
return head;
} void mem_pool_init() {
size_t l, i, s, n, b;
for (l=; l<MEM_BLOCK_TYPE_NUM; l++) {
i = 1 << l;
b = i * MEM_BLOCK;
s = b + sizeof(MemBlock);
n = mem_block_num(b); g_pool_mem[l] = (byte *)malloc(s * n);
if (NULL == g_pool_mem[l]) {
break;
}
g_pool[l] = mem_block_alloc(g_pool_mem[l], s, n);
}
return;
} void mem_pool_free() {
for (int i=; i<MEM_BLOCK_TYPE_NUM; i++) {
if (NULL != g_pool_mem[i]) {
free(g_pool_mem[i]);
g_pool_mem[i] = NULL;
g_pool[i] = NULL;
}
}
return;
} void* mem_get(size_t size) {
MemBlock* head = mem_block_head_get(size);
if (NULL == head) return NULL; do {
if (head->size == MEM_BLOCK_FREE) {
head->size = size;
return head->ptr;
} else {
head = head->next;
}
} while (head->next); return NULL;
} int mem_free(void **ptr) {
if (NULL == ptr || NULL == *ptr) return ; MemBlock *block = (MemBlock *)((byte*)(*ptr) - sizeof(MemBlock));
block->size = MEM_BLOCK_FREE; return ;
}
mem_pool_dlist.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "mem_pool.h" static byte* g_pool_buff[MEM_POOL_MAX] = {};
static MemBlockDlist* g_pool_objects[MEM_POOL_MAX] = {};
static MemBlockDlist* g_pool_freelist[MEM_POOL_MAX] = {};
static MemBlockDlist* g_pool_cursor[MEM_POOL_MAX] = {}; MemBlockDlist* mem_block_dlist_head(size_t index) {
if (index < || index >= MEM_POOL_MAX)
return NULL; return g_pool_objects[index];
} void mem_pool_cursor_init() {
for(size_t i=; i<MEM_POOL_MAX; i++)
g_pool_cursor[i] = mem_block_dlist_head(i);
} static MemBlockDlist* mem_block_dlist_alloc(byte* buf, int bk_size, int bk_num){
MemBlockDlist *head, *curr, *next;
int i; head = (MemBlockDlist *)buf;
head->size = MEM_BLOCK_FREE;
head->ptr = (byte*)head + sizeof(MemBlockDlist);
head->prev = NULL;
head->next = NULL; curr = head;
for (i=; i<bk_num; i++) {
next = (MemBlockDlist*)((byte*)curr + bk_size);
next->size = MEM_BLOCK_FREE;
next->ptr = (byte*)next + sizeof(MemBlockDlist); curr->next = next;
next->prev = curr;
next->next = NULL; curr = next;
}
return head;
} void mem_pool_dlist_init() {
size_t l, i, s, n, b;
for (l=; l<MEM_BLOCK_TYPE_NUM; l++) {
i = 1 << l;
b = i * MEM_BLOCK;
s = b + sizeof(MemBlockDlist);
n = mem_block_num(b); g_pool_buff[l] = (byte *)malloc(s * n);
if (NULL == g_pool_buff[l]) {
break;
}
g_pool_objects[l] = mem_block_dlist_alloc(g_pool_buff[l], s, n);
} mem_pool_cursor_init();
} void mem_pool_dlist_free() {
for (int i=; i<MEM_BLOCK_TYPE_NUM; i++) {
if (NULL != g_pool_buff[i]) {
free(g_pool_buff[i]); g_pool_buff[i] = NULL;
g_pool_objects[i] = NULL;
g_pool_freelist[i] = NULL;
g_pool_cursor[i] = NULL;
}
}
} MemBlockDlist* mem_free_block_get(int index) {
if (index < || index >= MEM_POOL_MAX) return NULL; MemBlockDlist* tmp = g_pool_freelist[index];
if (!tmp) return NULL; g_pool_freelist[index] = tmp->next;
g_pool_freelist[index]->prev = NULL;
tmp->next = NULL; return tmp;
} void* mem_realloc(size_t size) {
int index = mem_pool_index(size);
if (index < || index >= MEM_POOL_MAX)
return NULL; MemBlockDlist* ptr = mem_free_block_get(index);
if (ptr) {
ptr->size = size;
return ptr->ptr;
} MemBlockDlist* cursor = g_pool_cursor[index];
if (NULL == cursor) {
printf("pool index=%d memory leak or queue is all used.\n", index);
return NULL;
} if (MEM_BLOCK_FREE == cursor->size) {
g_pool_cursor[index] = cursor->next;
cursor->size = size;
return cursor->ptr;
} return NULL;
} void mem_release(void** ptr) {
if (NULL == ptr || NULL == *ptr)
return; size_t len = sizeof(MemBlockDlist);
MemBlockDlist *block = (MemBlockDlist *)((byte*)(*ptr) - len); int index = mem_pool_index(block->size);
if (index < || index >= MEM_POOL_MAX)
return; memset((byte*)(*ptr), , block->size);
MemBlockDlist* top = g_pool_freelist[index]; g_pool_freelist[index] = block;
if (top) {
g_pool_freelist[index]->next = top;
} g_pool_freelist[index]->size = MEM_BLOCK_FREE;
}
重复造轮子系列--内存池(C语言)的更多相关文章
- 重复造轮子系列——基于Ocelot实现类似支付宝接口模式的网关
重复造轮子系列——基于Ocelot实现类似支付宝接口模式的网关 引言 重复造轮子系列是自己平时的一些总结.有的轮子依赖社区提供的轮子为基础,这里把使用过程的一些觉得有意思的做个分享.有些思路或者方法在 ...
- 重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印
重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印 一.引言 桌面端系统经常需要对接各种硬件设备,比如扫描器.读卡器.打印机等. 这里介绍下桌面端 ...
- 重复造轮子系列--字符串处理(C语言)
这些字符代码是以前写的,源于很久很久以前的一个VC++项目,在当时的部门编程比赛里因为用了项目代码的xsplit函数,万万没想到,那个做了几年的项目里面居然有坑..xsplit函数居然不能split连 ...
- 重复造轮子系列--dijkstra算法
前年一时脑热(理想很丰满,现实很骨感),写了这个最短路径优先的低效版本,且留着回忆吧. spf.h #ifndef SPF_H_ #define SPF_H_ typedef struct { int ...
- 避免重复造轮子的UI自动化测试框架开发
一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览 ...
- 第27篇 重复造轮子---模拟IIS服务器
在写程序的时候,重复造轮子是程序员的一个大忌,很多人对重复造轮子持有反对的态度,但是我觉得这个造轮子的过程,是对于现有的知识的一个深入的探索的过程,虽然我们不可能把轮子造的那么的完善,对于现在有的东西 ...
- 重复造轮子,编写一个轻量级的异步写日志的实用工具类(LogAsyncWriter)
一说到写日志,大家可能推荐一堆的开源日志框架,如:Log4Net.NLog,这些日志框架确实也不错,比较强大也比较灵活,但也正因为又强大又灵活,导致我们使用他们时需要引用一些DLL,同时还要学习各种用 ...
- 54 个官方 Spring Boot Starters 出炉!别再重复造轮子了…….
在之前的文章,栈长介绍了 Spring Boot Starters,不清楚的可以点击链接进去看下. 前段时间 Spring Boot 2.4.0 也发布了,本文栈长再详细总结下最新的 Spring B ...
- GitHub Android 最火开源项目Top20 GitHub 上的开源项目不胜枚举,越来越多的开源项目正在迁移到GitHub平台上。基于不要重复造轮子的原则,了解当下比较流行的Android与iOS开源项目很是必要。利用这些项目,有时能够让你达到事半功倍的效果。
1. ActionBarSherlock(推荐) ActionBarSherlock应该算得上是GitHub上最火的Android开源项目了,它是一个独立的库,通过一个API和主题,开发者就可以很方便 ...
随机推荐
- 第一个AngularJS表达式实例
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- 用dockers实现mysql主从同步
首先要先看看当前的mysql的版本是什么,可以通过下面命令查看 mysql --version 最好是安装在docker中的mysql和你宿主机器中的mysql版本一致. 我的是mysql5.7.22 ...
- NestedScrollView和RecyclerView使用,并设置间距
NestedScrollView和RecyclerView使用,并设置间距: 效果图如下: 1.NestedScrollView 和RecyclerView嵌套问题(类似ScrollView 和lis ...
- iOS程序猿如何快速掌握 PHP,化身"全栈攻城狮"?
这是一篇以 iOS 开发人员的视角写给广大iOS 程序猿的 PHP 入门指南.在这篇文章里我努力去发掘 objectiv-c 与 php 之间的共性,来帮助有一定 iOS 开发经验的攻城狮来快速上手一 ...
- Easyui下的点击回车键跳转到下个控件
在Easyui框架下,JavaScript 中的 onKeyDown事件居然失效了.所以使用了另外的函数去实现点击回车键跳转到下个控件. /** * 点击回车键跳转到下个控件; * @param ol ...
- UVa中国麻将(Chinese Mahjong,Uva 11210)
简单的回溯题 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm ...
- Oracle字符集的查看查询和Oracle字符集的设置修改(转载)
本文主要讨论以下几个部分:如何查看查询oracle字符集. 修改设置字符集以及常见的Oracle UTF8字符集和Oracle exp 字符集问题. 一.什么是Oracle字符集 Oracle字符集是 ...
- expect配合shell 实现自动分发秘钥文件
expect使用场景 有时候需要批量地执行一些操作,或者执行自动化的操作的时候,有些指令需要交互式地进行这就会有很多麻烦,linux下有一个程序交expect,它可以模拟键盘输入文本,省去人工干预交互 ...
- Linux常见文件管理命令
1.Linux上的文件管理类命令都有哪些,其常用的使用方法及其相关示例演示.(1)目录管理命令——ls:列出指定目录下的内容格式:ls [OPTION]... [FILE]... -a:显示所有文件包 ...
- 2、spring boot 配置文件
配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的: •application.properties •application.yml 配置文件的作用:修改SpringBoot自 ...