--=比天空间=-- - 查看单个帖子 - nginx upstream hash代码查看

来源:百度文库 编辑:神马文学网 时间:2024/05/15 20:17:39
主题: nginx upstream hash代码查看 查看单个帖子 05-14-2009, 13:49   #7 iamok 管理员
注册日期: Sep 2004 帖子: 5,017 Status: Offline
ngx_http_script_compile

分析

其中的ngx_array_create是一个在pool中分配内存的东西,
代码:
ngx_array_t *                ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size)                {                ngx_array_t *a;                a = ngx_palloc(p, sizeof(ngx_array_t));                if (a == NULL) {                return NULL;                }                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;                }                


他先分配一个ngx_array_t大小的空间给a

然后再分配一个 n*size大小的空间地址头给a中的elts这个指针.

然后更新a中的nelts为0
size为size
nalloc为n
pool为p

然后返回a这个指针地址.



先判断sc->flushes的指针和具体的数值是否为空.
然后就利用ngx_array_create为*sc->flushes这个指针分配内存地址.

接着判断sc-length是否为空,为空就调用ngx_array_create分配内存.

这里还搞不懂为啥n的大小为
代码:
sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)                + sizeof(ngx_http_script_var_code_t))                + sizeof(uintptr_t)                


后面也是同样的手法来分配sc->values的内存空间.

还是不理解为啥这时候n是
代码:
(sc->variables * (2 * sizeof(ngx_http_script_copy_code_t)                + sizeof(ngx_http_script_var_code_t))                + sizeof(uintptr_t)                + sc->source->len                + sizeof(uintptr_t) - 1)                & ~(sizeof(uintptr_t) - 1)                

然后重置了sc->variables的值为0

-------------------------------------

这里花点时间说一下sc里面的几个东西的赋值情况

首先
代码:
value = cf->args->elts;

这个cf->args->elts是一个指针类型,至于指向什么具体类型没有定义.

value被定义成指向 ngx_str_t 这样的指针,

而随后的 代码:
sc.source = &value[1] 

表示 value是一个包含 ngx_str_t指针的数组,也就是说,在这个函数里
cf->args->elts是一个包含ngx_str_t的数组,上面的语法说明 sc.source被分赋值成了 数组的第二个元素(ngx_str_t类型的元素)


代码:
    vars_lengths = NULL;                vars_values = NULL;

表示var_lengths和vars_values都被初始化成null了.
代码:
   sc.cf = cf;                sc.source = &value[1];                sc.lengths = &vars_lengths;                sc.values = &vars_values;                sc.complete_lengths = 1;                sc.complete_values = 1;                

分别是 cf这个ngx_conf_t被复制给了sc.cf

sc.source上面介绍过了

sc.lengths和sc.values都被赋值给 指向 ngx_array_t 指针的指针了.

sc.complete_lengths和sc.complete_values都被初始化成1了.

--------------------------------------------------------------------

接着就是一个for循环对 source里面的ngx_str_t类型的数据进行解析.

这个for循环是一个不完整的条件循环
代码:
  for (i = 0; i < sc->source->len; /* void */ )

他先判断data部分的第一个char是否为$,如果是,就 ++i 看看是否到字串的尾部了,
看具体代码: 代码:
 if (++i == sc->source->len) {                goto invalid_variable;                }                

这样就巧妙的在程序的主体部分进行了字串位置的偏移,而不是在for部分,奇怪的做法
如果到尾部,就goto到 invalid_variable 部分.

接着看.

接着就判断后面的部分是不是1-9,如果是1-9,就把sc->source->data[i] - '0' 后赋值给 n
这里减字符0的做法有点费解,都比较了字符了,为啥还要减字符0,为了确保变成整数么.暂时先这么想吧.

接着用几行代码做了mask码的操作,我还不了解具体的mask的含义,先记着.
代码:
                if (sc->captures_mask & (1 << n)) {                sc->dup_capture = 1;                }                sc->captures_mask |= 1 << n;                

然后 调用了一个新的函数 代码:
 ngx_http_script_add_code(*sc->lengths,                sizeof(ngx_http_script_copy_capture_code_t),                NULL);


其中 ngx_http_script_copy_capture_code_t 数据结构的内部是这样的.
代码:
typedef struct {                ngx_http_script_code_pt          code;                uintptr_t                        n;                } ngx_http_script_copy_capture_code_t;                




先来看看这个新的函数 ngx_http_script_add_code

------------------------------------------------------------------------

因为调用它的时候,第三个参数为NULL,所以函数内部主要只是做了一个动作
代码:
 new = ngx_array_push_n(codes, size);

来看看 ngx_array_push_n 的内容...
代码:
size = n * a->size;

首先他先计算一下 外面传递进来的size个数,和 已经分配内存空间的 ngx_array_t->size的乘积.

然后他判断 代码:
 if (a->nelts + n > a->nalloc)

是说判断未使用的是否够n

如果不够,就看看这个pool里面是否还有多余的空间
代码:
        if ((u_char *) a->elts + a->size * a->nalloc == p->d.last                && p->d.last + size <= p->d.end)


如果还有空间,就移动d.last到size位置的偏移量,然后更新a->nalloc

如果没有空间,就分配新的 代码:
new = ngx_palloc(p, nalloc * a->size);

最后调用ngx_memcpy
代码:
ngx_memcpy(new, a->elts, a->nelts * a->size);

ngx_memcpy实际上是一个宏
代码:
#define ngx_memcpy(dst, src, n)   (void) memcpy(dst, src, n)

然后更新 a里对应值
代码:
 a->elts = new;                a->nalloc = nalloc;

这里有个问题,就是原来的内存空间就浪费了,而且没法free,因为pool是一个链表结构,没法free,而只能是覆盖写


然后偏移a->elts为具体的已经分配的array的大小
代码:
elt = (u_char *) a->elts + a->size * a->nelts;

同时更新a->nelts
代码:
a->nelts += n;

然后返回片以后的a->elts地址.


总结,ngx_array_push_n的功能就是,返回偏移了已经使用过的array元素大小的ngx_array_t->elts的指针. 这个指针就是可以开始使用的没有数据的内存地址.
如果ngx_array_t的大小不够,或者pool的大小不够,ngx_array_push_n会自动帮你扩展的.


---------------------------------------------------

这样 ngx_http_script_add_code 就返回了

第一个参数里面的可以使用的->elts地址. iamok 查看公开的资料 查找iamok发表的更多帖子 添加iamok到你的好友列表