nginx是一个高性能的HTTP和反向代理web服务器,是由伊戈尔·塞索耶夫为俄罗斯网站开发的,是一个开源的软件,底层由C语言编写完成,但经过提炼后,是可以将其按照面向对象的思想重新组织一下的,也相当于一个小项目吧。
涉及思路是将源文件中的几个主要函数实现成为类的成员方法,成员变量则只设置一个内存池对象即可。因为nginx内存池的结构比较复杂,涉及很多网络相关的东西,我们在本地编译器上对这些变量做了简化。
一、主要结构
源码中的一些结构体我们依旧使用结构体来实现,首先减免一些不必要的变量,防止在本地编译过程中增加不必要的麻烦。
//清理函数(回调函数)的类型
typedef void(*ngx_pool_cleanup_pt)(void *data);
struct ngx_pool_cleanup_s
{
ngx_pool_cleanup_pt handler;//定义了一个函数指针,保存清理操作的回调函数
void *data;//传递给回调函数的参数
ngx_pool_cleanup_s *next;//所有的clean_up清理操作都被穿在链表上
};
//大块内存的头部信息
struct ngx_pool_large_s
{
ngx_pool_large_s *next;//大块内存串起来
void *alloc;//保存分配出去的大块内存的起始地址
};
//分配小块内存的数据头
typedef struct ngx_pool_data_t
{
u_char *last;//小块内存池可用内存的起始地址
u_char *end;//小块内存池可用内存的末尾地址
ngx_pool_s *next;//用于连接所有的小块内存
ngx_uint_t failed;//记录当前小块内存分配失败的次数
};
//内存池头部信息和管理成员信息
struct ngx_pool_s
{
ngx_pool_data_t d;//存储头信息
size_t max;//小块内存和大块内存的分界
ngx_pool_s *current;//指向第一个可分配的内存块
ngx_pool_large_s *large;//指向大块内存的入口地址
ngx_pool_cleanup_s *cleanup;//清理占用的外部资源
};
二、全局变量的定义
因为在源码中使用了大量的宏定义来实现数值的替换,而在C++中我们则使用const关键字来替换源码中的宏,源码中使用了typedef关键字来进行类型重命名,在C++中我们使用C++11的using关键字来实现类型重定义,这是在代码上做的改变。
//类型重定义
using u_char = unsigned char;
using ngx_uint_t = unsigned int;
//把buff缓冲区清零
#define ngx_memzero(buf, n) (void) memset(buf, 0, n)
//把数值d调整到临近的a的倍数
#define ngx_align(d, a) (((d) + (a - 1)) & ~(a - 1))
//小块内存分配考虑字节对齐时的单位
#define NGX_ALIGNMENT sizeof(unsigned long)
//把指针p调整到a的临近的倍数
#define ngx_align_ptr(p, a) \
(u_char *) (((uintptr_t) (p) + ((uintptr_t) a - 1)) & ~((uintptr_t) a - 1))
//默认物理页面的大小
const int ngx_pagesize = 4096;
//需要使用NGINX内存池分配的大小,超过则不统一管理
const int NGX_MAX_ALLOC_FROM_POOL = ngx_pagesize - 1;
//nginx内存池的默认大小
const int NGX_DEFAULT_POOL_SIZE = 16 * 1024;
//内存对齐的量
const int NGX_POOL_ALIGNMENT = 16;
//ngx小块内存池最小的size调整成NGX_POOL_ALIGNMENT的临近的倍数
const int NGX_MIN_POOL_SIZE =
ngx_align((sizeof(ngx_pool_s) + 2 * sizeof(ngx_pool_large_s)),
NGX_POOL_ALIGNMENT);
以上是一些标准量的定义,比如页面大小等等,在后续的实现中会陆续使用到。
三、类的定义
代码移植的整体思想是将内存池改为面向对象的思想,所以要对其方法以及变量进行封装,成员方法在类内只做声明,而在类外定义。
class ngx_mem_pool
{
public:
//创建指定size大小的内存池,小块内存池不超过一个页面大小
void* ngx_create_pool(size_t size);
//考虑内存字节对齐,从内存池申请size大小的内存
void *ngx_palloc(size_t size);
//不考虑内存字节对齐
void *ngx_pnalloc(size_t size);
//调用pnalloc,并对内存块初始化为0
void *ngx_pcalloc(size_t size);
//释放大块内存
void ngx_pfree(void *p);
//内存池重置函数
void ngx_reset_pool();
//内存池销毁函数
void ngx_destroy_pool();
//添加回调的清理操作函数
ngx_pool_cleanup_s *ngx_pool_cleanup_add(size_t size);
private:
ngx_pool_s *pool;//指向nginx内存池的入口指针
//小块内存分配
void *ngx_palloc_small(size_t size,ngx_uint_t align);
//分配新的小块内存池
void *ngx_palloc_block(size_t size);
//大块内存分配
void