需求:
由于Nginx源码中并没有提供ngx_realloc和ngx_prealloc方法,因此在2011年10月,为Tengine(淘宝版Nginx)源码贡献这两个方法的实现;
解决方案:
在介绍解决方案之前,需要先介绍下realloc的功能定义:
下面介绍代码实现:
// ngx_realloc代码实现及分析 // 首先定义一个用于返回的new指针,并通过C的realloc方法为传入的指针p重新分配空间, // 若返回为null则将错误信息写入nginx错误日志,否则将debug信息写入nginx debug日志并返回新地址空间的指针 void * ngx_realloc(void *p, size_t size, ngx_log_t *log) { void *new; new = realloc(p, size); if (new == NULL) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "realloc(%p:%uz) failed", p, size); } ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, log, 0, "realloc: %p:%uz", new, size); return new; }
// ngx_prealloc代码实现及分析
void * ngx_prealloc(ngx_pool_t *pool, void *p, size_t old_size, size_t new_size) { void *new; // 如果p为空,则相对于在pool中分配一块新空间并返回指向该空间的指针 if (p == NULL) { return ngx_palloc(pool, new_size); } // 如果所需重新分配的空间大小为0,则判断旧空间地址是否在pool的最后, // 若是,则只需将pool的d.last指针移到旧空间地址的起始位置; // 否则,使用ngx_pfree方法是否pool中的旧空间; // 最后返回null。 if (new_size == 0) { if ((u_char *) p + old_size == pool->d.last) { pool->d.last = p; } else { ngx_pfree(pool, p); } return NULL; } // 如果所需重新分配的空间处于pool的最后,并且pool剩余空间 // 的大小大于所需分配空间的大小,则只需将pool的d.last指向 // 新空间的末尾并返回原空间的地址即可。 if ((u_char *) p + old_size == pool->d.last && (u_char *) p + new_size <= pool->d.end) { pool->d.last = (u_char *) p + new_size; return p; } // 如果以上条件均不符合,则需要通过ngx_palloc在pool内分配 // 一个新的空间,并在将旧空间内的数据拷贝到新空间内之后, // 释放掉旧空间,返回新空间地址。 new = ngx_palloc(pool, new_size); if (new == NULL) { return NULL; } ngx_memcpy(new, p, old_size); ngx_pfree(pool, p); return new; }
ok, 全部介绍完毕。