日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

nginx学习七 高级数据结构之动态数组ngx_array_t

發(fā)布時(shí)間:2025/6/15 52 豆豆
生活随笔 收集整理的這篇文章主要介紹了 nginx学习七 高级数据结构之动态数组ngx_array_t 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1 ngx_array_t結(jié)構(gòu)

ngx_array_t是nginx內(nèi)部使用的數(shù)組結(jié)構(gòu)。nginx的數(shù)組結(jié)構(gòu)在存儲(chǔ)上與大家認(rèn)知的C語(yǔ)言?xún)?nèi)置的數(shù)組有相似性。比方實(shí)際上存儲(chǔ)數(shù)據(jù)的區(qū)域也是一大塊連續(xù)的內(nèi)存。

可是數(shù)組除了存儲(chǔ)數(shù)據(jù)的內(nèi)存以外還包括一些元信息來(lái)描寫(xiě)敘述相關(guān)的一些信息,而且能夠動(dòng)態(tài)增長(zhǎng)。以下

我們從數(shù)組的定義上來(lái)具體的了解一下。

ngx_array_t的定義位于src/core/ngx_array.c|h里面。

struct ngx_array_s {void *elts;//數(shù)組的首地址ngx_uint_t nelts;//數(shù)組中已經(jīng)使用的元素個(gè)數(shù)size_t size; //每一個(gè)元素占用的內(nèi)存大小ngx_uint_t nalloc;//當(dāng)前數(shù)組中可以容納元素的個(gè)數(shù)ngx_pool_t *pool; //內(nèi)存池對(duì)象 }; elts指向存儲(chǔ)數(shù)據(jù)內(nèi)存的起始地址。

nelts是數(shù)組中實(shí)際已經(jīng)存儲(chǔ)的元素個(gè)數(shù)

size是每一個(gè)數(shù)組元素占用內(nèi)存的大小。比方int占用4個(gè)字節(jié)的大小,size=4。

nalloc是數(shù)組空間大小。

pool成員函數(shù)負(fù)責(zé)管理數(shù)組使用的內(nèi)存。


2函數(shù)操作

nginx為數(shù)組提供了五個(gè)操作函數(shù)例如以下:

//創(chuàng)建一個(gè)動(dòng)態(tài)數(shù)組。數(shù)組的大小為n,每一個(gè)元素的大小為size
ngx_array_t *ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size);

//銷(xiāo)毀已分配的動(dòng)態(tài)數(shù)組元素空間和動(dòng)態(tài)數(shù)組對(duì)象
void ngx_array_destroy(ngx_array_t *a);

//向數(shù)組中加入一個(gè)元素,返回這個(gè)新元素的地址。假設(shè)數(shù)組空間已經(jīng)用完,數(shù)組會(huì)自己主動(dòng)擴(kuò)充空間
void *ngx_array_push(ngx_array_t *a);

//向數(shù)組中加入n個(gè)元素,返回這n個(gè)元素中第一個(gè)元素的地址
void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);

//和create函數(shù)的功能差點(diǎn)兒相同,僅僅只是這個(gè)array不能為空,返回值為是否初始化成功
static ngx_inline ngx_int_t
ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size)

2.1ngx_array_create


ngx_array_t *ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size);
創(chuàng)建一個(gè)數(shù)組,p是內(nèi)存池對(duì)象, n為數(shù)組存儲(chǔ)元素的個(gè)數(shù), size為每一個(gè)元素占用的空間大小。

來(lái)看看源碼:

ngx_array_t * ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size) {ngx_array_t *a;//1:創(chuàng)建ngx_array_t指針。這個(gè)array的內(nèi)存也是在p上申請(qǐng)的a = ngx_palloc(p, sizeof(ngx_array_t));if (a == NULL) {return NULL;}//2:申請(qǐng)數(shù)組存儲(chǔ)元素的內(nèi)存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;//返回?cái)?shù)組指針 }

2.2 ngx_array_destroy

void ngx_array_destroy(ngx_array_t *a);

回收已分配給數(shù)組的內(nèi)存,包含數(shù)組本身。看源碼:

void ngx_array_destroy(ngx_array_t *a) {ngx_pool_t *p;p = a->pool;//1:銷(xiāo)毀數(shù)組存儲(chǔ)元素的內(nèi)存,即數(shù)據(jù)區(qū)的內(nèi)存if ((u_char *) a->elts + a->size * a->nalloc == p->d.last) {p->d.last -= a->size * a->nalloc;}//2:銷(xiāo)毀數(shù)組本身的內(nèi)存,即結(jié)構(gòu)體array本身的內(nèi)存//a = ngx_palloc(p, sizeof(ngx_array_t));這句代碼申請(qǐng)的內(nèi)存if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) {p->d.last = (u_char *) a;} }2.3 ngx_array_push

void *ngx_array_push(ngx_array_t *a);

向數(shù)組中加入元素。而且返回新添加元素的地址。看源代碼:

void * ngx_array_push(ngx_array_t *a) {void *elt, *new;size_t size;ngx_pool_t *p;if (a->nelts == a->nalloc) {//數(shù)組已滿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)//假設(shè)p的剩余空間>=一個(gè)數(shù)組元素的空間。就分配一個(gè)空間給數(shù)組{p->d.last += a->size;//調(diào)整pool的last。即改動(dòng)下一次可分配空間的事實(shí)上地址a->nalloc++;} else {new = ngx_palloc(p, 2 * size);//申請(qǐng)新的空間,大小是原來(lái)的2倍,假如pool的內(nèi)存不足夠分配一個(gè)新的數(shù)組元素if (new == NULL) {return NULL;}ngx_memcpy(new, a->elts, size);//把原有的元素復(fù)制到新分配的內(nèi)存區(qū)a->elts = new;//改動(dòng)數(shù)組數(shù)據(jù)區(qū)的地址,使其指向新分配的內(nèi)存區(qū)a->nalloc *= 2;//改動(dòng)數(shù)組可容納的元素個(gè)數(shù),是原來(lái)容納元素的2倍}}elt = (u_char *) a->elts + a->size * a->nelts;//新添加元素的地址a->nelts++;//數(shù)組中元素的個(gè)數(shù)加1return elt;//返回新添加元素的地址 }
調(diào)用這個(gè)函數(shù)并沒(méi)用真的加入進(jìn)元素,它僅僅是返回新加元素將要被放入數(shù)組的地址,我們必須按例如以下操作才干真正的加入如元素:

//加入一個(gè)int元素 ngx_int_t* elem; elem = ngx_array_push(array);//得到新增元素地址 *elem = 10;
2.4ngx_array_push_n

void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);

向數(shù)組中加入n個(gè)元素。返回這n個(gè)元素中第一個(gè)元素的地址。


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;size = n * a->size;if (a->nelts + n > a->nalloc) {//數(shù)組已滿p = a->pool;if ((u_char *) a->elts + a->size * a->nalloc == p->d.last&& p->d.last + size <= p->d.end)//假設(shè)pool剩余的內(nèi)存可以容納這n個(gè)元素,就不用又一次分配內(nèi)存{p->d.last += size;//改動(dòng)last使其指向可分配內(nèi)存的起始地址a->nalloc += n;//數(shù)組容納元素個(gè)數(shù)+n} else {//假設(shè)pool剩余的內(nèi)存不可以容納這n個(gè)元素。就又一次分配內(nèi)存nalloc = 2 * ((n >= a->nalloc) ?

n : a->nalloc);//申請(qǐng)2倍的內(nèi)存 new = ngx_palloc(p, nalloc * a->size); if (new == NULL) { return NULL; } ngx_memcpy(new, a->elts, a->nelts * a->size);//把原有的元素復(fù)制到新申請(qǐng)的內(nèi)存中 a->elts = new;//改動(dòng)數(shù)組元素區(qū)的地址 a->nalloc = nalloc;//改動(dòng)數(shù)組可以容納的元素個(gè)數(shù) } } elt = (u_char *) a->elts + a->size * a->nelts;//新增元素的首地址 a->nelts += n;//已存儲(chǔ)元素個(gè)數(shù)+n return elt; }


2.5 ngx_array_init

ngx_int_t ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size);

和create函數(shù)的功能差點(diǎn)兒相同,僅僅只是這個(gè)array不能為空,返回值為是否初始化成功

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,array不能為空array->nelts = 0;array->size = size;array->nalloc = n;array->pool = pool;array->elts = ngx_palloc(pool, n * size);//申請(qǐng)內(nèi)存空間if (array->elts == NULL) {return NGX_ERROR;}return NGX_OK; }
3 ngx_array_t的一個(gè)使用

void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);

/* author: smtl date: 2014-09-28 */#include <stdio.h> #include <stdlib.h> #include <ngx_core.h> #include <ngx_config.h> #include <ngx_conf_file.h> #include <nginx.h> #include <ngx_string.h> #include <ngx_palloc.h> #include <ngx_array.h>//不加以下這兩個(gè)定義編譯會(huì)出錯(cuò) volatile ngx_cycle_t *ngx_cycle;void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,const char *fmt, ...) { }int main()//too many migical number {ngx_pool_t* pool = ngx_create_pool(2048, NULL);if (pool == NULL){printf("create pool failed\n");exit(1);}ngx_array_t* array = ngx_array_create(pool, 20, sizeof(ngx_int_t));if (array == NULL){printf("array alloc failed\n");exit(1);}ngx_int_t i;ngx_int_t* elem;for (i=0; i<20; ++i){elem = ngx_array_push(array);//加入元素*elem = i;}elem = (int*)array->elts;for (i=0; i<20; ++i){printf("array[%d] = %d \n", i, elem[i]);}printf("加入10個(gè)元素:\n");ngx_int_t n = 10;elem = ngx_array_push_n(array, n);for (i=0; i<n; ++i){elem[i] = 20 + i;}elem = (int*)array->elts;for (i=20; i<20+n; ++i){printf("array[%d] = %d \n", i, elem[i]);}ngx_array_destroy(array);printf("ngx_array_int:\n");array = ngx_pcalloc(pool, sizeof(ngx_array_t));//注意這個(gè)函數(shù)和ngx_array_create的差別。array不能為空ngx_array_init(array, pool, 20, sizeof(ngx_int_t));for (i=0; i<20; ++i){elem = ngx_array_push(array);//加入元素*elem = rand()%1000;}elem = array->elts;for (i=0; i<20; ++i){printf("array[%d] = %d \n", i, elem[i]);}ngx_destroy_pool(pool);return 0; }

http://blog.csdn.net/xiaoliangsky/article/details/39647771

總結(jié)

以上是生活随笔為你收集整理的nginx学习七 高级数据结构之动态数组ngx_array_t的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。