创见内存怎么样 创建服务器内存( 二 )


static ngx_inline void *
ngx_palloc_small(ngx_pool_t *pool, size_t size, ngx_uint_t align)
{
u_char*m;
ngx_pool_t*p;
p = pool->current;// 从 current 处开始分配合适的内存
do {
m = p->d.last;
if (align) {// 是否需要内存对齐
m = ngx_align_ptr(m, NGX_ALIGNMENT);
}
// 当前小块内存池的剩余容量满足申请的内存
if ((size_t) (p->d.end – m) >= size) {
p->d.last = m + size;
return m;// 一旦满足分配直接退出
}
p = p->d.next;// 不满足的情况下寻找下一个小块内存池
} while (p);
return ngx_palloc_block(pool, size); // 没有满足分配的内存池,再申请一个小块内存池
}
当在小块内存池中找到了合适的内存后的结构如下:


创见内存怎么样 创建服务器内存

文章插图
文章插图

当没有小块内存池满足申请时,会再申请一个小块内存池来满足分配,在设置完 last 和 end 两个内存指示器后,对从 current 开始的内存池成员 failed 进行自增操作,并且当这个内存池的 failed 分配次数大于 4 时,表面这个内存分配失败的次数太多,根据经验应该下一次分配可能还是失败,所以直接跳过这个内存池,移动 current 。
C/C++Linux服务器开发高级架构师学习文档电子书籍 点击 正在跳转 获取,内容知识点包括Linux,Nginx,ZeroMQ,MySQL,Redis,线程池,MongoDB,ZK,Linux内核,CDN,P2P,epoll,Docker,TCP/IP,协程,DPDK等等 。视频学习链接点击:C/C++Linux服务器开发/后台架构师【零声教育】-学习视频教程-腾讯课堂

创见内存怎么样 创建服务器内存

文章插图
文章插图

新的内存块插入至内存池链表的尾端 。
#define NGX_ALIGNMENTsizeof(unsigned long)// 8
static void *
ngx_palloc_block(ngx_pool_t *pool, size_t size)
{
u_char*m;
size_tpsize;
ngx_pool_t*p, *new;
psize = (size_t) (pool->d.end – (u_char *) pool);// 每一个内存池的大小都相同
m = ngx_memalign(NGX_POOL_ALIGNMENT, psize, pool->log);// 16 字节对齐申请
if (m == NULL) {
return NULL;
}
new = (ngx_pool_t *) m;
new->d.end = m + psize;
new->d.next = NULL;
new->d.failed = 0;
m += sizeof(ngx_pool_data_t);
m = ngx_align_ptr(m, NGX_ALIGNMENT);
new->d.last = m + size;
for (p = pool->current; p->d.next; p = p->d.next) {
if (p->d.failed++ > 4) {
pool->current = p->d.next;
}
}
p->d.next = new;// 尾插法插入至链表末端
return m;
}
分配一块内存池后逻辑结构如下:

创见内存怎么样 创建服务器内存

文章插图
文章插图

大块内存申请大块内存是通过 large 连接的,并且都属于 ngx_create_pool 返回的 ngx_pool_t 结构 。malloc 分配的内存由一个 ngx_pool_large_t 节点来挂载,而这个 ngx_pool_large_t 节点又是从小块内存池中分配的 。
为避免large链表长度过大导致在遍历寻找空闲挂载节点耗时过长,限制了遍历的节点为3,如果没有满足要求则直接分配头插法 插入至large链表中,新的节点后面也是最先被访问static void *
ngx_palloc_large(ngx_pool_t *pool, size_t size)
{
void*p;
ngx_uint_tn;
ngx_pool_large_t*large;
p = ngx_alloc(size, pool->log);// 调用 malloc
if (p == NULL) {
return NULL;
}
n = 0;
for (large = pool->large; large; large = large->next) {// 从large 中链表中找到 alloc 为 NULL 的节点,将分配的内存挂在该节点上

经验总结扩展阅读