Nginx原始碼完全註釋(2)ngx_array.h / ngx_array.c
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 "array->nelts" before "array->elts", otherwise MSVC thinks
* that "array->nelts" 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.csdn.net/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的新浪微博
-
相關文章
- Nginx原始碼完全註釋(6)core/murmurhashNginx原始碼
- Nginx原始碼完全註釋(8)ngx_errno.cNginx原始碼
- Nginx原始碼完全註釋(9)nginx.c: ngx_get_optionsNginx原始碼
- Nginx原始碼完全註釋(5)core/ngx_cpuinfo.cNginx原始碼UI
- 原始碼完全註釋:socket select原始碼
- Nginx原始碼完全註釋(1)ngx_alloc.h / ngx_alloc.cNginx原始碼
- Nginx原始碼完全註釋(7)ngx_palloc.h/ngx_palloc.cNginx原始碼
- Nginx原始碼完全註釋(4)ngx_queue.h / ngx_queue.cNginx原始碼
- Nginx原始碼完全註釋(3)ngx_list.h / ngx_list.cNginx原始碼
- Nginx 原始碼完全剖析(11)ngx_spinlockNginx原始碼
- Nginx 原始碼完全剖析(10)ngx_radix_treeNginx原始碼
- 《Linux核心完全註釋》學習筆記:2.7 Linux核心原始碼的目錄結構Linux筆記原始碼
- HashMap原始碼(JDK1.8)-手動註釋HashMap原始碼JDK
- Bootstrap的Model原始碼詳細註釋 (轉)boot原始碼
- Nginx篇--Nginx原始碼搭建Nginx原始碼
- EventBus原始碼解讀詳細註釋(2)MainThread執行緒模型分析原始碼AIthread執行緒模型
- Redux原始碼完全解讀Redux原始碼
- egis釋出了adsubstract pro 2.1註冊器,帶原始碼的。 (2千字)原始碼
- bootstrap-modal.js學習筆記(原始碼註釋)bootJS筆記原始碼
- Dubbo原始碼解析之服務釋出與註冊原始碼
- 從Python原始碼註釋,自動生成API文件Python原始碼API
- 使用ehcache元註釋提高Spring 效能原始碼案例Spring原始碼
- C231n-KNN-assignment1-完全程式碼及註釋KNN
- C231n-SVM-assignment1-完全程式碼及註釋
- nginx原始碼安裝Nginx原始碼
- NGINX原始碼閱讀Nginx原始碼
- Nginx 原始碼安裝Nginx原始碼
- 原始碼安裝Nginx原始碼Nginx
- Nginx的nginx.conf配置檔案中文註釋說明Nginx
- CSS程式碼註釋CSS
- php程式碼註釋PHP
- maven下載原始碼,解決中文註釋為亂碼的問題Maven原始碼
- DialogFragment使用到原始碼完全解析Fragment原始碼
- docker原始碼安裝NginxDocker原始碼Nginx
- macbook 原始碼安裝 nginxMac原始碼Nginx
- Centos原始碼安裝NginxCentOS原始碼Nginx
- ArcGIS VBA - VBA+AO入門15例完全註釋版
- snownlp類庫(中文情感分析)原始碼註釋及使用原始碼