ngnix内存池主要函数实现(个人学习笔记)

一.简介

 内存池可以提高内存申请的效率,还可以一定程度避免内存泄漏。

这是一个仿照ngnix实现的内存池,学习后把自己的理解写上去了。

二.内存池结构

内存池结构体主要分为三部分,小数据内存分配块,大文件内存分配块,还有一个清理函数部分,他们都是通过链表存储的。

(一).小数据内存分配块

struct ngx_pool_data_t
{
	char* last;//已经分配到的地方,可以分配的起始地址
	char* end;//数据块大小
	ngx_pool_t* next;//下一个数据块
	int count;//访问次数
};

 这个结构体使用的时候,last记录的是上次分配内存后,剩余内存的起始地址

#include<iostream>
#include<fstream>
using namespace std;

class ngx_pool_t;
struct ngx_pool_data_t
{
	char* last;//已经分配到的地方,可以分配的起始地址
	char* end;//数据块大小
	ngx_pool_t* next;//下一个数据块
	int count;//访问次数
};

struct ngx_pool_large_t
{
	ngx_pool_large_t* next;//下一个大内存块
	void* alloc;//内存的首地址
};

struct ngx_pool_cleanup
{
	void* data;
	//回调函数
	ngx_pool_cleanup* next;
};

struct ngx_pool_log
{
	ofstream* pof;
};

struct ngx_pool_t
{
	ngx_pool_data_t* d;//数据块
	int max;//可以分配内存的最大值


	ngx_pool_t* current;//当前块
	ngx_pool_large_t* large;//大文件链表
	ngx_pool_cleanup* cleanup;//清除链表
	ngx_pool_log* log;
};


void ngx_errno_log()
{

}


void* ngx_alloc(size_t size, ngx_pool_log* log)//申请大小为size的空间
{
	void* p;
	p = malloc(size);
	if (p == NULL)
	{
		//失败打印日志
		*(log->pof) << "malloc faild " << endl;
		//返回空
		return nullptr;
	}
	//写进日志,malloc:%p size:size
	*(log->pof) << "malloc:" << hex << p << "size :" << size << endl;
	return p;
}


//把size大小的内存清零
void ngx_memzero(void* p, int size)
{
	char *pm = static_cast<char*>(p);
	for (int i = 0; i < size; i++)
	{
		*(pm + i) = 0;
	}
}


void* ngx_calloc(size_t size, ngx_pool_log* log)//申请大小为size的空间,并清零
{
	void* p;
	p = ngx_alloc(size, log);
	if (p)
	{
		ngx_memzero(p, size);
	}
	return p;
}

//应该有一个内存对其操作,这里只是转换了类型
ngx_pool_t* ngx_calloc_align(int size,ngx_pool_log * log)
{
	return static_cast<ngx_pool_t*>(ngx_calloc(size, log));
}


//创建内存池
ngx_pool_t* ngx_pool_create(int size,ngx_pool_log *log)
{
	ngx_pool_t* p;
	p = ngx_calloc_align(size, log);
	if (p == NULL)
	{
		//打印到日志里初始化失败
		*(log->pof) << "ngx_pool_create failed : NULL" << endl;
 		return NULL;
	}

	p->d->last = (char*)p + sizeof(ngx_pool_t);//内存分配的起始地址
	p->d->count = 0;//该内存块读取次数
	p->d->end = (char*)p + size;//这个数据块的结束地址
	p->d->next = nullptr;//下一个数据块

	p->max = size - sizeof(ngx_pool_t);

	p->current = p;
	p->large = nullptr;
	p->cleanup = nullptr;
	p->log = nullptr;

	return p;
}


//释放大块
void ngx_free_large(ngx_pool_large_t* t, ngx_pool_log* log)
{
	*(log->pof) << "free: " << hex << t->alloc;
	free(t->alloc);
}



//销毁内存池
void ngx_destroy_tool(ngx_pool_t* pool)
{
	//清除cleanup链表
	ngx_pool_cleanup* c;
	for (c = pool->cleanup; c; c = c->next)
	{
		//调用回调函数
	}


	//清除large链表
	ngx_pool_large_t* t;
	for (t = pool->large; t; t->next)
	{
		if (t->alloc != nullptr)
		{
			//*(pool->log->pof) << "free: " << hex << t->alloc;
			//free(t->alloc);
			ngx_free_large(t, pool->log);
		}
	}


	//清除数据块
	ngx_pool_t *p;
	ngx_pool_t* n;
	for (p = pool, n = pool->d->next;; p = n, n = n->d->next)
	{
		free(p);
		if (n == nullptr)
		{
			break;
		}
	}


}



//重设内存池,清除大块,数据段收回
void ngx_ret_pool(ngx_pool_t* pool)
{
	//清除大块
	for (ngx_pool_large_t* t = pool->large; t; t = t->next)
	{
		if (t->alloc == nullptr)
		{
			ngx_free_large(t, pool->log);
		}
	}

	//清除数据块,就是重设d->last指针
	pool->d->last = pool->d->end - sizeof(ngx_pool_t);
	for (ngx_pool_t* p = pool->d->next; p; p = p->d->next)
	{
		p->d->last = p->d->end - sizeof(ngx_pool_data_t);
	}



}


//数据块申请
void* ngx_palloc_block(ngx_pool_t* pool, int size)
{
	char* m;
	//申请新的空间
	int psize = pool->d->end - (char*)pool;
	ngx_pool_t* pnew = ngx_calloc_align(psize, pool->log);

	//设置这片空间
	m = (char*)pnew + sizeof(pool->d);
	pnew->d->end = (char*)pnew + psize;
	pnew->d->last = m + size;
	pnew->d->count = 0;
	pnew->d->next = nullptr;


	ngx_pool_t* p;

	for (p = pool->current; p->d->next; p = p->d->next)
	{
	}

	p->d->next = pnew;

	return m;


}



//大内存申请
void* ngx_palloc_large(ngx_pool_t* pool, int size)
{
	void* m = ngx_alloc(size, pool->log);
	ngx_pool_large_t* large;
	int n = 1;
	for (large = pool->large; large->next; large = large->next)
	{
		if (large->alloc == nullptr)
		{
			large->alloc = m;
			return m;
		}
		if (n++ >= 3)
		{
			break;
		}
	}



	large = (ngx_pool_large_t*)ngx_palloc(pool, size);
	if (large == NULL)
	{
		*(pool->log->pof) << "free :" << hex << m;
		free(m);
	}
}





//申请一块大小为size的空间
void* ngx_palloc(ngx_pool_t* pool, int size)
{
	//返回的起始地址
	char* m;
	ngx_pool_t* p;

	//size小于等于最大值,用数据块分配
	if (size <= pool->max)
	{
		p = pool->current;
		do
		{
			//ngx这里有一个内存对齐
			if (p->d->end - size >= p->d->last)
			{

				m = p->d->last;
				p->d->last += size;
				return m;
			}
			p = p->d->next;
		} while (p);


		return ngx_palloc_block(pool, size);
		//遍历data链表没有,就重新申请一个block
	}
	
	//走大块内存分配
	return ngx_palloc_large(pool, size);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值