设为首页 收藏本站
查看: 496|回复: 0

[经验分享] Apache源代码分析——配置命令执行过程

[复制链接]
累计签到:29 天
连续签到:1 天
发表于 2017-1-10 07:14:57 | 显示全部楼层 |阅读模式
转载请注名来源:http://blog.csdn.net/tingya
该文章分析了Apache中的配置命令执行过程
该部分是与前面的命令表的部分紧密关联的,因此阅读这部分请先阅读前面的命令表分析。

////////////////////////////////////////////////////////////////////////////
static const char *invoke_cmd(const command_rec *cmd, cmd_parms *parms,
               void *mconfig, const char *args)
apache内部对命令的实现最终是通过invoke_cmd实现的,在invoke_cmd的基础之上进行了简单的包装,构成了execute_now函数。
函数首先检测该指令是否出现在它应该出现的地方。这个可以通过将通过AllowOverride设置的parms->override和cmd->req_override进行比较,如果相等,则表明合法,否则表明指令不应该出现在这个位置。
函数最终将根据cmd->args_how来进行实际的函数调用,args_how指明了调用函数的实际的原型。首先我们看一下最简单的args_how为RAW_ARGS的情况,简化后函数的相关执行语句如下:
switch (cmd->args_how) {
  case RAW_ARGS:
    return cmd->AP_RAW_ARGS(parms, mconfig, args);
……
}
在cmd中我们声明了执行函数为func,其类型为cmd_fun。在前面我们说过不同指令最终实际的函数原型是不一样,其函数的参数由args_how决定,那么Apache是如何作到仅用一个函数名就达到调用各种不同函数的目的的呢。在C++下这个倒是可以通过重载实现,而C中则没有直接的方法。为此Apache采取了一些变通的方法。我们看一下下面的定义就会明白实现策略了。
typedef union {
  const char *(*no_args) (cmd_parms *parms, void *mconfig);
  const char *(*raw_args) (cmd_parms *parms, void *mconfig,
  const char *args);
  const char *(*take1) (cmd_parms *parms, void *mconfig, const char *w);
  const char *(*take2) (cmd_parms *parms, void *mconfig, const char *w,
const char *w2);
  const char *(*take3) (cmd_parms *parms, void *mconfig, const char *w,
const char *w2, const char *w3);
  const char *(*flag) (cmd_parms *parms, void *mconfig, int on);
} cmd_func
我们现在就会发现cmd_func原来是一个联合类型,apache将所有可能用到的函数原型都放在里面的。因此需要的时候只需要从中去取就可以了。那么现在我们在看看宏AP_RAW_ARGS的实现:
# define AP_RAW_ARGS func.raw_args
原来AP_RAW_ARGS宏无非就是用来获取RAW_ARGS类型指令处理函数的名字,一旦得到名称就可以将参数传递进去,进行类似下面的函数调用:
cmd->AP_RAW_ARGS(parms, mconfig, args);
至此,函数开始执行指令对应的函数。所有的指令的调用都大同小异,因此我们不再对调用方式做过多的描述,我们下面来看看不同类型的指令apache是如何处理的。
(1),对于RAW_ARGS类型的指令,服务器不对其做任何修改,因此,传进来什么参数,服务器原封不动的再传给指令处理函数。
(2),NO_ARGS类型指令也很简单,服务器什么都不需要传入给执行函数。
(3),如果是TAKE1类型的指令,由于指令后面带一个参数,为此必须得到该参数,函数将调用ap_getword_conf得到该参数,然后将其传入处理函数。对于TAKE1指令,即使后面存在多个指令参数,处理器也只取第一个。
(4),如果是TAKE2或者TAKE3指令,处理方法与TAKE1指令类似,只是要调用两次或三次ap_getword_conf得到个个参数。如果指令后面所带的参数不能满足要求,函数将报错,返回错误信息。
(5),如果指令是TAKE12,TAKE13,TAKE23或者TAKE123,处理函数处理之前必须保证指令参数在规定范围之内。如果不足,相应参数设置为NULL。
(6),如果指令是ITERATE,那么指令的参数个数将不确定,为此处理器将循环迭代调用ap_getword_conf,每次取一个参数,然后调用TAKE1指令处理函数;处理完继续取下一个,处理代码如下:
while (*(w = ap_getword_conf(parms->pool, &args)) != '') {
errmsg = cmd->AP_TAKE1(parms, mconfig, w);
if (errmsg && strcmp(errmsg, DECLINE_CMD) != 0)
return errmsg;
}
(7),ITERATE2指令与ITERAT1不同,其对指令的迭代处理是从第二个参数开始,第一个指令不参与迭代。处理器取出第一个参数后,然后将它和第二个参数开始的每一个参数联合作为指令函数的两个处理参数,处理代码如下:
w = ap_getword_conf(parms->pool, &args);
……
while (*(w2 = ap_getword_conf(parms->pool, &args)) != '') {
errmsg = cmd->AP_TAKE2(parms, mconfig, w, w2);
……
}
(8),FLAG指令与前面的所有指令处理方法都不一样,该指令后面的参数只有两种:On和Off,其余的都是非法。如果为“On”,传递给处理函数的相应参数为1,否则为0,具体代码如下:
w = ap_getword_conf(parms->pool, &args);
if (*w == '' || (strcasecmp(w, "on") && strcasecmp(w, "off")))
return apr_pstrcat(parms->pool, cmd->name, " must be On or Off",NULL);
return cmd->AP_FLAG(parms, mconfig, strcasecmp(w, "off") != 0);

关于作者
张中庆,目前主要的研究方向是嵌入式浏览器,移动中间件以及大规模服务器设计。目前正在进行Apache的源代码分析,计划出版《Apache源代码全景分析》上下册。Apache系列文章为本书的草案部分,对Apache感兴趣的朋友可以通过flydish1234 at sina.com.cn与之联系!

如果你觉得本文不错,请点击文后的“推荐本文”链接!!

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-326179-1-1.html 上篇帖子: Apache中多任务并发处理机制研究(1) 下篇帖子: [一步一步Felix]了解Apache Felix OSGi容器
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表