【nginx流程分析之指针使用】

写在前面

这个篇章主要是为了解释nginx的一些指针的使用,以及为什么要这么使用。同时也是为了更好的理解整个流程。如果有希望理解整个的可以看nginx之流程分析

ngx_init_cycle之配置文件

首先来看第一个地方,也就是ngx_cycle_s的这个结构体
四层指针

初始化conf_ctx

从图片中可以看出来,这个ngx_cycle_s中定义了一个类型为void,然后名称为conf_ctx的四层指针,然后来看一下初始化的地方:
在这里插入图片描述
这一段代码是在 /nginx-1.14.2/src/core/ngx_cycle.c 中的ngx_init_cycle方法中。然后ngx_pcalloc是分析了一段178个8字节(void *)的连续内存。这个ngx_pcalloc返回的是void * 。因为conf_ctx是四层指针,ngx_pcalloc返回的是一层指针,所以conf_ctx实际就是一层指针。如图所示
在这里插入图片描述
这里我们假设开始的地址是0x13b8175c0。

问题

问:第一个地址是0x13b8175c0,怎么获取第二个内存地址?
答: cycle->conf_ctx +1。这个也是比较简单,直接移动指针就好了。

conf_ctx赋值

然后看接下来nginx的操作,就是对conf_ctx进行操作
在这里插入图片描述
结合注释我们看出来,其实就是初始化nginx的 ngx_core_conf_t(主配置文件),然后因为NGX_CORE_MODULE的index也就是cycle->modules[i]->index =0,然后就是把conf_ctx的第一个地址指向了ngx_core_conf_t的地址。
注意:这边的 cycle->conf_ctx[cycle->modules[i]->index] = rv; 并不是把cycle->conf_ctx的地址进行了覆盖(当然内存地址是固定,也不可能覆盖对于物理内存来说),而是指向了rv的地址,然后就是如图所示:
在这里插入图片描述

所以我们可以看到其实ctx->conf_ctx是一个二层指针。然后我们继续看nginx的操作。

初始化ngx_conf_s的ctx

首先我们看一下ngx_conf_s的结构体。因为cycle是ngx_conf_s的一个成员,可以看到
在这里插入图片描述

然后注意这边的一个ctx,定义类型void *的类型。然后看nginx的操作,
在这里插入图片描述

然后可以看到把cycle_ctx的四层指针,赋值给了ctx的这个一层指针。不着急我们还是根据上图分析,这里我们不要把几层指针难到了,我们只要注意是这个指针是指向哪里就好了,然后我们继续看对应的关系图:
在这里插入图片描述

然后可以看出来ctx=conf_ctx,所以其实ctx也同时指向了0x13b8175c0这个地址,也就是128块地址的开始的地址。

问题

接下来做几个问题帮助理解:

得到ctx首地址

答案1 conf.ctx。
答案2 &((void **)conf.ctx)[0]。 这个答案可能看起来有点蒙,这个对我们后面看nginx的指针很有帮助,所以我们慢慢分析:
2.1 先类型转换
因为conf.ctx指向了0x13b8175c0的地址,而0x13b8175c0是指向了rv。所以conf.ctx是一个二级指针,所以用(void **) 进行类型转换。
2.2 [0]的意义
根据我们的分析,这个是指向了0x13b8175c0的指向的地方,也就是rv的地址,也就是 0x13b8180f0。 然后再用&取地址,所以我们又回到了0x13b8175c0的地址。

获取rv的地址

如果看懂上面也就很简单了,答案就是*((void **)conf.ctx),对(void **)conf.ctx) 进行取值

获取配置

这个方法在 /nginx-1.14.2/src/core/ngx_conf_file.c中的ngx_conf_handler方法。
在这里插入图片描述

((void **) cf->ctx)[cf->cycle->modules[i]->index]

然后我们先看看conf = ((void **) cf->ctx)[cf->cycle->modules[i]->index];
然后这边cf->cycle->modules[i]->index 是等于0的,
然后这个结合上面可以看出,是已经初始化了,就是 cycle->conf_ctx[cycle->modules[i]->index] = rv。然后conf就是rv;地址是0x13b8180f0

&(((void **) cf->ctx)[cf->cycle->modules[i]->index])

然后看看 conf = &(((void **) cf->ctx)[cf->cycle->modules[i]->index]);
这个就比较的特殊了,前面多加了一个取地址的&符号,这个我们慢慢分析。首先是(((void **) cf->ctx)[cf->cycle->modules[i]->index]);这个其实和上面的一样,是指向了cf-ctx的cf->cycle->modules[i]->index所指向的地址,然后这个和上面的不一样,并没有初始化,因为需要加一个&。
打个比方我们ctx->conf_ctx的第一个地址是0x13b8175c0,然后第二个地址是0x13b8175c8,因为集合我们上面的图看,这个地址没有任何指向,所以加一个&重新指向了自己。
然后我们可以看到,这边就是用(void **)转换成了二级指针,然后再去判断是否初始化。因为通常来说没有初始化,所以(void **) conf = null
在这里插入图片描述

*(void **) ((char *) cf->ctx + cmd->conf)

这个和上面的两个一样的道理。这个留给读者思考哈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值