Skip to content

Commit

Permalink
Merge branch 'master' of github.com:its-tech/nginx-1.14.0-research
Browse files Browse the repository at this point in the history
  • Loading branch information
叶剑峰 committed Jun 19, 2018
2 parents c81ca82 + b0d6588 commit 0a68406
Show file tree
Hide file tree
Showing 10 changed files with 303 additions and 141 deletions.
2 changes: 1 addition & 1 deletion configure
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ if [ "$NGX_PLATFORM" != win32 ]; then
. auto/unix
fi

# 如果打开了线程池支持,那么就会检查是否操作系统支持县城
# 如果打开了线程池支持,那么就会检查是否操作系统支持线程
. auto/threads

# 最核心的构造运行期modules的脚本。
Expand Down
51 changes: 43 additions & 8 deletions src/core/ngx_array.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,16 @@
#include <ngx_config.h>
#include <ngx_core.h>


/**
* 从内存池中创建n个元素的数组,元素大小为size
* 创建一个新的数组对象,并返回这个对象。
* @param p: 数组分配内存使用的内存池;
* @param n: 数组的初始容量大小,即在不扩容的情况下最多可以容纳的元素个数。
* @param size: 单个元素的大小,单位是字节。
*
* 注意事项: 由于使用ngx_palloc分配内存,数组在扩容时,旧的内存不会被释放,会造成内存的浪费。
* 因此,最好能提前规划好数组的容量,在创建或者初始化的时候一次搞定,避免多次扩容,造成内存浪费。
*/
ngx_array_t *
ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size)
{
Expand All @@ -34,6 +43,16 @@ ngx_array_destroy(ngx_array_t *a)

p = a->pool;

/**
* PS:你估计比较奇怪,为何数组的内存空间一定会分配在内存池(pool->d存储小内存)上面
* 如果比较大的内存块不是会存储在内存池的pool->large上面吗?
* 当我们全局搜索Nginx代码中ngx_array_create方法的时候发现,Nginx的数组都是比较小的,存储的数据量也
* 并不是很大。所以ngx_array_t适合存储小块的内存。
*/
/**
* 如果数组元素的末尾地址和内存池pool的可用开始的地址相同
* 则将内存池pool->d.last移动到数组元素的开始地址,相当于清除当前数组的内容(使pool内存可以重用)
*/
if ((u_char *) a->elts + a->size * a->nalloc == p->d.last) {
p->d.last -= a->size * a->nalloc;
}
Expand All @@ -43,14 +62,22 @@ ngx_array_destroy(ngx_array_t *a)
}
}


/**
* 在数组a上新追加一个元素,并返回指向新元素的指针。
* 需要把返回的指针使用类型转换,转换为具体的类型,然后再给新元素本身或者是各字段(如果数组的元素是复杂类型)赋值。
* 如果数组已满,则重新分配两倍(nalloc*size)的内存空间,且nalloc更新为2*nalloc
*
* @param a
* @return
*/
void *
ngx_array_push(ngx_array_t *a)
{
void *elt, *new;
size_t size;
ngx_pool_t *p;

//数组元素等于数组容量时
if (a->nelts == a->nalloc) {

/* the array is full */
Expand All @@ -59,6 +86,13 @@ ngx_array_push(ngx_array_t *a)

p = a->pool;

/**
* 扩容有两种方式
* 1.如果数组元素的末尾和内存池pool的可用开始的地址相同,
* 并且内存池剩余的空间支持数组扩容,则在当前内存池上扩容
* 2. 如果扩容的大小超出了当前内存池剩余的容量或者数组元素的末尾和内存池pool的可用开始的地址不相同,
* 则需要重新分配一个新的内存块存储数组,并且将原数组拷贝到新的地址上
*/
if ((u_char *) a->elts + size == p->d.last
&& p->d.last + a->size <= p->d.end)
{
Expand All @@ -72,25 +106,26 @@ ngx_array_push(ngx_array_t *a)

} else {
/* allocate a new array */

/* 重新分配一个 2*size的内存块 */
new = ngx_palloc(p, 2 * size);
if (new == NULL) {
return NULL;
}

ngx_memcpy(new, a->elts, size);
a->elts = new;
a->nalloc *= 2;
ngx_memcpy(new, a->elts, size); //内存块拷贝,将老的内存块拷贝到新的new内存块上面
a->elts = new; //内存块指针地址改变
a->nalloc *= 2; //分配的个数*2
}
}

//最新的内存地址
elt = (u_char *) a->elts + a->size * a->nelts;
a->nelts++;
a->nelts++; //只分配一个元素,所以元素+1

return elt;
}


//跟上面方法相同,只不过支持多个元素
void *
ngx_array_push_n(ngx_array_t *a, ngx_uint_t n)
{
Expand Down
32 changes: 24 additions & 8 deletions src/core/ngx_array.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,38 @@
#include <ngx_config.h>
#include <ngx_core.h>


//数组Array数据结构
typedef struct {
void *elts;
ngx_uint_t nelts;
size_t size;
ngx_uint_t nalloc;
ngx_pool_t *pool;
void *elts; //指向实际的数据存储区域
ngx_uint_t nelts; //数组实际元素个数
size_t size; //数组单个元素大小
ngx_uint_t nalloc; //数组的容量。表示该数组在不引发扩容的前提下,可以最多存储的元素的个数。当nelts增长到达nalloc 时,如果再往此数组中存储元素,则会引发数组的扩容。数组的容量将会扩展到原有容量的2倍大小。实际上是分配新的一块内存,新的一块内存的大小是原有内存大小的2倍。原有的数据会被拷贝到新的一块内存中。
ngx_pool_t *pool; //该数组用来分配内存的内存池。
} ngx_array_t;


/*
从内存池中创建n个元素的数组,元素大小为size
创建一个新的数组对象,并返回这个对象。
p: 数组分配内存使用的内存池;
n: 数组的初始容量大小,即在不扩容的情况下最多可以容纳的元素个数。
size: 单个元素的大小,单位是字节。
注意事项: 由于使用ngx_palloc分配内存,数组在扩容时,旧的内存不会被释放,会造成内存的浪费。
因此,最好能提前规划好数组的容量,在创建或者初始化的时候一次搞定,避免多次扩容,造成内存浪费。
*/
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);

// 在数组a上新追加一个元素,并返回指向新元素的指针。
// 需要把返回的指针使用类型转换,转换为具体的类型,然后再给新元素本身或者是各字段(如果数组的元素是复杂类型)赋值。
// 如果数组已满,则重新分配两倍(nalloc*size)的内存空间,且nalloc更新为2*nalloc
void *ngx_array_push(ngx_array_t *a);
// 返回将要添加n个元素到数组中其首个元素的地址
void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);


// 如果一个数组对象是被分配在堆上的,那么当调用ngx_array_destroy销毁以后,如果想再次使用,就可以调用此函数。
// 如果一个数组对象是被分配在栈上的,那么就需要调用此函数,进行初始化的工作以后,才可以使用。
static ngx_inline ngx_int_t
ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size)
{
Expand Down
59 changes: 43 additions & 16 deletions src/core/ngx_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@
#include <ngx_config.h>
#include <ngx_core.h>


/*从内存池中分配一块size大小的缓冲区,内部成员初始化好,temporary设为1*/
ngx_buf_t *
ngx_create_temp_buf(ngx_pool_t *pool, size_t size)
{
ngx_buf_t *b;

/* 最终调用的是内存池pool,开辟一段内存用作缓冲区,主要放置ngx_buf_t结构体 */
b = ngx_calloc_buf(pool);
if (b == NULL) {
return NULL;
}

/* 分配缓冲区内存; pool为内存池,size为buf的大小*/
b->start = ngx_palloc(pool, size);
if (b->start == NULL) {
return NULL;
Expand All @@ -43,19 +45,22 @@ ngx_create_temp_buf(ngx_pool_t *pool, size_t size)
return b;
}


//从内存池中获取ngx_chian_t对象
ngx_chain_t *
ngx_alloc_chain_link(ngx_pool_t *pool)
{
ngx_chain_t *cl;

/*
* 首先从内存池中去取ngx_chain_t,
* 被清空的ngx_chain_t结构都会放在pool->chain 缓冲链上
*/
cl = pool->chain;

if (cl) {
pool->chain = cl->next;
return cl;
}

/* 如果取不到,则从内存池pool上分配一个数据结构 */
cl = ngx_palloc(pool, sizeof(ngx_chain_t));
if (cl == NULL) {
return NULL;
Expand All @@ -64,21 +69,22 @@ ngx_alloc_chain_link(ngx_pool_t *pool)
return cl;
}


//一次创建多个缓冲区,返回一个连接好的链表
ngx_chain_t *
ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs)
{
u_char *p;
ngx_int_t i;
ngx_buf_t *b;
ngx_chain_t *chain, *cl, **ll;
ngx_chain_t *chain, *cl, **ll; //ll代表指针的指针

p = ngx_palloc(pool, bufs->num * bufs->size);
if (p == NULL) {
return NULL;
}

ll = &chain;
//用ll来交换指针变量地址
ll = &chain; //chain的地址赋值给ll,使用*ll作赋值操作时会改变chain的指针

for (i = 0; i < bufs->num; i++) {

Expand Down Expand Up @@ -107,41 +113,47 @@ ngx_create_chain_of_bufs(ngx_pool_t *pool, ngx_bufs_t *bufs)
p += bufs->size;
b->end = p;

//分配一个nginx_chain_t
cl = ngx_alloc_chain_link(pool);
if (cl == NULL) {
return NULL;
}

/* 将buf,都挂载到ngx_chain_t链表上,最终返回ngx_chain_t链表 */
cl->buf = b;
*ll = cl;
ll = &cl->next;
*ll = cl; //ll相同地址的对象,chain等于cl
ll = &cl->next; //cl->next的地址赋值给ll,使用*ll作赋值操作时会改变cl->next的指针
}

*ll = NULL;

return chain;
}


/**
* 将其它缓冲区链表放到已有缓冲区链表结构的尾部
*/
ngx_int_t
ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain, ngx_chain_t *in)
{
ngx_chain_t *cl, **ll;

ll = chain;

/* 找到缓冲区链表结尾部分,cl->next== NULL;cl = *chain既为指针链表地址*/
for (cl = *chain; cl; cl = cl->next) {
ll = &cl->next;
ll = &cl->next; //设置ll的指向对象
}

//依次将in链表中的节点插入到chain链表末尾
while (in) {
cl = ngx_alloc_chain_link(pool);
if (cl == NULL) {
return NGX_ERROR;
}

cl->buf = in->buf;
*ll = cl;
*ll = cl; //*ll被赋值操作,会改变chain链表尾部指针
ll = &cl->next;
in = in->next;
}
Expand All @@ -151,19 +163,21 @@ ngx_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain, ngx_chain_t *in)
return NGX_OK;
}


/*从空闲的buf链表上,获取一个未使用的buf链表*/
ngx_chain_t *
ngx_chain_get_free_buf(ngx_pool_t *p, ngx_chain_t **free)
{
ngx_chain_t *cl;

/*空闲列表有数据,则直接返回一个链表*/
if (*free) {
cl = *free;
*free = cl->next;
cl->next = NULL;
return cl;
}

/*分配一个新的buf*/
cl = ngx_alloc_chain_link(p);
if (cl == NULL) {
return NULL;
Expand All @@ -179,18 +193,28 @@ ngx_chain_get_free_buf(ngx_pool_t *p, ngx_chain_t **free)
return cl;
}


/**
* 将busy链表中的空闲节点回收到free链表中
*
* @param p
* @param free 空闲链表
* @param busy busy链表
* @param out 已输出链表
* @param tag 需要释放buf的标记
*/
void
ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free, ngx_chain_t **busy,
ngx_chain_t **out, ngx_buf_tag_t tag)
{
ngx_chain_t *cl;

/*将已输出out链表放到busy链表上*/
if (*out) {
if (*busy == NULL) {
*busy = *out;
*busy = *out; //busy直接指向out链表

} else {
//找到busy链表的最后一个节点
for (cl = *busy; cl->next; cl = cl->next) { /* void */ }

cl->next = *out;
Expand All @@ -201,20 +225,23 @@ ngx_chain_update_chains(ngx_pool_t *p, ngx_chain_t **free, ngx_chain_t **busy,

while (*busy) {
cl = *busy;

//合并后的该busy链表节点有内容时,则表示剩余节点都有内容,则退出
if (ngx_buf_size(cl->buf) != 0) {
break;
}

//如果该busy链表节点不属于tag指向的模块,则跳过。
if (cl->buf->tag != tag) {
*busy = cl->next;
ngx_free_chain(p, cl);
continue;
}

//重置buf缓冲区所有空间都可用
cl->buf->pos = cl->buf->start;
cl->buf->last = cl->buf->start;

//将该空闲空闲区加入到free链表表头
*busy = cl->next;
cl->next = *free;
*free = cl;
Expand Down
Loading

0 comments on commit 0a68406

Please sign in to comment.