设为首页 收藏本站
查看: 660|回复: 0

[经验分享] Nginx源码完全注释(2)ngx_array.h / ngx_array.c

[复制链接]

尚未签到

发表于 2015-11-13 14:08:14 | 显示全部楼层 |阅读模式
Nginx源码完全注释(2)ngx_array.h / ngx_array.c

  • 作者:柳大·Poechant(钟超)
  • 邮箱:zhongchao.ustc#gmail.com(# -> @)
  • 博客:Blog.CSDN.net/Poechant
  • 日期:August 15th, 2012
数组头文件 ngx_array.h

#include <ngx_config.h>
#include <ngx_core.h>
struct ngx_array_s {
void        *elts;
ngx_uint_t   nelts;
size_t       size;
ngx_uint_t   nalloc;
ngx_pool_t  *pool;
};
ngx_array_t *ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size);
void ngx_array_destroy(ngx_array_t *a);
void *ngx_array_push(ngx_array_t *a);
void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);
// 初始化似乎没什么好说的
static ngx_inline ngx_int_t
ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size)
{
/*
* set &quot;array->nelts&quot; before &quot;array->elts&quot;, otherwise MSVC thinks
* that &quot;array->nelts&quot; may be used without having been initialized
*/

array->nelts = 0;
array->size = size;
array->nalloc = n;
array->pool = pool;
array->elts = ngx_palloc(pool, n * size);
if (array->elts == NULL) {
return NGX_ERROR;
}
return NGX_OK;
}
数组源文件 ngx_array.c

#include <ngx_config.h>
#include <ngx_core.h>
/* 创建一个 Nginx 数组,内存池地址为 p,元素个数为 n,每个元素大小为 size */
ngx_array_t *
ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size)
{
ngx_array_t *a;
// 调用 ngx_palloc,从 内存池 p,为 Nginx 数组 a 分配内存
a = ngx_palloc(p, sizeof(ngx_array_t));
if (a == NULL) {
return NULL;
}
// 调用 ngx_palloc,为 Nginx 数组 a 的 elts 分配内存,大小为 n * size
a->elts = ngx_palloc(p, n * size);
if (a->elts == NULL) {
return NULL;
}
// 注意,上面是先分配定义结构区,再定义数据存储区
// 其他初始化项
a->nelts = 0; // 已存元素数
a->size = size; // 每个元素大小(字节)
a->nalloc = n; // 最大元素数
a->pool = p; // 内存池地址
return a;
}

void
ngx_array_destroy(ngx_array_t *a)
{
ngx_pool_t  *p;
// 数组 a 的内存池地址
p = a->pool;
// 数组 a 的最大存储区的末尾,到了内存池的已用区域的末尾(可用区的开头)
// 即表示内存池目前最后一段存储的是一个数组的存储区
if ((u_char *) a->elts + a->size * a->nalloc == p->d.last) {
// 内存池已用区域末尾向前挪(每个元素大小 x 最大元素个数)字节
p->d.last -= a->size * a->nalloc;
}
// 数组 a 结构体所占用内存的末尾,为内存池的可用区的开头
// 即表示内存池目前最后一段存储的是一个数组的结构体
if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) {
p->d.last = (u_char *) a;
}
// 上面先剪掉数据存储区,再剪掉定义结构区
}

void *
ngx_array_push(ngx_array_t *a)
{
void        *elt, *new;
size_t       size;
ngx_pool_t  *p;
// 数组满了,即已存储元素数 nelts 已达到最大容纳数 nalloc
if (a->nelts == a->nalloc) {
/* the array is full */
// size 为数组的最大容量(最大容纳数 x 每个元素大小)
size = a->size * a->nalloc;
p = a->pool;
// 数组的数据存储区的末尾,到达了内存池的已用区域的末尾
// 且,内存池的已用区域末尾的下一个位置<=内存池的末尾,就是说内存池还有够用的剩余空间
if ((u_char *) a->elts + size == p->d.last
&& p->d.last + a->size <= p->d.end)
{
/*
* the array allocation is the last in the pool
* and there is space for new allocation
*/

// 分配一个元素,就得把 last 往下挪一个,即已用区域往下挪一个
p->d.last += a->size;
// 分配一个元素,且内存池没满,就得把“最大元素数”加1
a->nalloc++;
} else { // 内存池剩余空间不够
/* allocate a new array */
// 分配一个两倍的空间(原来空间的两倍)
new = ngx_palloc(p, 2 * size);
if (new == NULL) {
return NULL;
}
// 把 a->elts 的东东拷贝到 new 里,拷贝 size 字节个数据
ngx_memcpy(new, a->elts, size);
a->elts = new; // 新地址
a->nalloc *= 2; // 新最大容量
// size 不变(最大容量,即单个元素大小 x 最大元素数)
// pool 不变
// nelts 已用元素数不变
}
}
// elt 为已用数据区的末尾
elt = (u_char *) a->elts + a->size * a->nelts;
// 已存数据个数加 1
a->nelts++;
// 返回这个已用数据区的末尾(可用数据区的开头,或者说是下一个元素可以用的位置)
return elt;
}

void *
ngx_array_push_n(ngx_array_t *a, ngx_uint_t n)
{
void        *elt, *new;
size_t       size;
ngx_uint_t   nalloc;
ngx_pool_t  *p;
// 要放的 n 个元素所占的总字节数
size = n * a->size;
// 已存元素数 + 要存的 n 个元素 > 最大容量(最大元素数)
if (a->nelts + n > a->nalloc) {
/* the array is full */
p = a->pool;
// 数组的数据存储区的末尾,到达了内存池的已用区域的末尾
// 且,内存池的已用区域末尾的下一个位置<=内存池的末尾,就是说内存池还有够用的剩余空间
if ((u_char *) a->elts + a->size * a->nalloc == p->d.last
&& p->d.last + size <= p->d.end)
{
/*
* the array allocation is the last in the pool
* and there is space for new allocation
*/

// 分配 n 个元素,就得把 last 往后挪 size = n * a->size
p->d.last += size;
// 分配 n 个元素,且内存池没满,就得把“最大元素数(最大容量)”加 n
a->nalloc += n;
} else { // 内存池剩余空间不够
/* allocate a new array */
// 准备分配一个两倍的空间,nalloc是新空间的大小
// (如果原来最大容量大,则分配原来空间的两倍;如果新要的n个元素更多,则分配n的两倍)
nalloc = 2 * ((n >= a->nalloc) ? n : a->nalloc);
// 分配新空间
new = ngx_palloc(p, nalloc * a->size);
if (new == NULL) {
return NULL;
}
// 把老空间的东东,拷贝到新空间
ngx_memcpy(new, a->elts, a->nelts * a->size);
// elts 新空间地址
a->elts = new;
// nalloc 数组最大容量
a->nalloc = nalloc;
}
}
// 要放入的 n 个元素的起始位置
elt = (u_char *) a->elts + a->size * a->nelts;
// 已用元素数加 n
a->nelts += n;
// 返回n个东东的位置
return elt;
}
Reference

  • http://blog.iyunv.com/v_july_v/article/details/7040425
  • http://www.cnblogs.com/sld666666/archive/2010/06/27/1766255.html
  • http://www.cnblogs.com/jzhlin/archive/2012/06/05/Nginx_pool.html
  • http://code.google.com/p/nginxsrp/wiki/NginxCodeReview#ngx的内存池
-
转载请注明来自柳大Poechant(钟超Michael)的CSDN博客:
钟超Michael的博客:Blog.CSDN.net/Poechant
钟超Michael的微博:钟超Michael的新浪微博
-
   
版权声明:本文为博主原创文章,未经博主允许不得转载。合作请联系微信 sinosuperman。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-138842-1-1.html 上篇帖子: Nginx基本数据结构之ngx_queue_t 下篇帖子: nginx 灰度发布 请大神指教,在线等
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表