该文章分析了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与之联系!
如果你觉得本文不错,请点击文后的“推荐本文”链接!!
相关推荐
Source Insight 3.1 介绍——Linux 内核源代码分析工具(二) Source Insight 3.1 是一款功能强大且专业的 Linux 内核源代码分析工具。该工具可以帮助开发者快速地分析和理解 Linux 内核源代码,提高开发效率和质量...
《DVWA源代码详解——深度剖析Web安全漏洞与防护》 DVWA(Damn Vulnerable Web Application)是一款专门用于Web安全教育的开源应用,其全称为“极其易受攻击的Web应用”。DVWA的设计目的是为安全专业人员提供一个...
Apache是由Apache软件基金会开发的一款开放源代码的Web服务器,它的普及率极高,据数据显示,超过65%的网站都基于Apache来运行。 Apache服务器的主要特点包括: 1. **完全免费**:Apache服务器遵循开源协议,用户...
1. **下载**:从Apache官方网站(WWW.apache.org)获取最新版本的Apache源代码,例如版本2.0.63。 2. **解压**:使用`tar`命令解压缩下载的文件,生成相应的源代码目录。 3. **配置**:进入源代码目录,使用`...
10. **实战案例**:书中源代码可能涵盖实际数据分析任务,如网页爬取、日志分析等,这些实例能帮助读者将理论知识应用于实践。 通过对《Hadoop权威指南》源代码的深度学习,开发者能够更深入地理解Hadoop的工作原理...
标题中的“mod_mono源代码 与 Win32下.so文件”指的是Apache服务器上的一个扩展模块——mod_mono,它是用于在Windows环境下运行.NET应用程序的关键组件。这个模块使得Apache能够托管基于.NET Framework(或其开源...
6. **编译与配置**:在获取到OpenSSL源代码后,开发者需要通过配置脚本(config或Configure)指定编译选项,然后使用make命令编译和安装。这个过程可能需要根据目标系统的特性进行调整。 7. **应用集成**:OpenSSL...
2. **获取Apache源代码**:从Apache官方网站下载最新版本的源代码。 3. **解压源代码**:使用`tar`命令解压缩下载的源代码。 4. **配置Apache**:进入源代码目录,使用`./configure`命令配置Apache,指定需要的...
3. SQL解析:源代码可能包含一个SQL解析器,用于将用户输入的SQL语句转换为可执行的命令,这涉及到编译原理和正则表达式。 4. GUI设计:如果sqlt是图形界面应用,那么会涉及到GUI框架(如Java的Swing或Qt)的使用,...
例如,maven-compiler-plugin用于编译Java源代码,maven-surefire-plugin负责执行单元测试。 4. **依赖管理**:Maven使用传递性依赖管理,如果项目A依赖于项目B,而项目B又依赖于项目C,那么在构建项目A时,Maven会...
在这个安装过程中,我们将深入探讨如何从源码编译并安装Apache 2.2.17,同时也会提及两个特定的模块——`mod_fileiri.c`和`mod_fileiri.so`。 首先,我们需要了解源码安装的基本步骤。在Linux或Unix系统中,这通常...
这个过程对于用户来说是透明的,用户无需编写MapReduce代码,只需要用HQL进行数据查询和分析即可。 Hive的表与HDFS目录紧密相关,Hive表中的数据被存储在HDFS的目录中,而表的元数据则存储在MySQL数据库中。这意味...
- 通过编写特定的源代码,将IntraWeb项目编译为一个动态链接库(.so文件)。这一步骤中需要定义`apache_modulename`,例如:`IWDSOProject_module`。 - 编译完成后会得到一个名为`IWDSOProject.so`的文件,该文件...
此外,Maven插件系统允许扩展其功能,覆盖从源代码格式化到自动化测试的各类任务。 总的来说,Apache Maven 3.3.9作为一个强大的项目管理和构建工具,通过依赖管理和标准化的构建流程,极大地简化了Java开发的工作...
用户在下载完成后,需要先用gunzip命令解压gz文件,然后用tar命令解压tar文件,最后才能得到可配置和编译的源代码。以下是基本的命令行操作流程: 1. `gunzip httpd-2.2.4.tar.gz`:解压gzip压缩文件。 2. `tar -...
Maven通过读取`pom.xml`文件来自动化构建过程,包括编译源代码、运行测试、打包、生成文档和部署应用。 "Maven 打包"标签强调了Maven在构建过程中的一个重要功能——打包。Maven可以将Java源代码编译成JAR、WAR或...
3. **构建**:通过命令行运行`mvn compile`,Maven会编译源代码;运行`mvn package`,Maven会打包项目,生成JAR或WAR文件。 4. **测试**:Maven可以执行单元测试,如JUnit,结果会自动记录在报告中。 5. **部署**:...
本系统分析了Linux操作系统的特点、远程管理的各种方法和...而在Linux系统中,默认的Apache用户权限是无法访问管理系统所需文件,无法运行关键系统命令的,因此,需要对Apache服务器进行一些特殊配置,提升其权限,
通过POM文件,Maven可以自动下载所需的库文件,编译源代码,运行测试,打包应用,甚至部署到服务器。 了解并掌握Maven的安装和基本配置是Java开发者的基本技能之一。随着对Maven的深入使用,你会发现它在构建、管理...
这些许可证规定了其他人可以如何使用、修改和分发源代码。 9. **部署与扩展**:此工具可能支持IIS或Azure等平台的快速部署。同时,源码的开放性使得用户可以根据需求进行自定义修改,比如增加新的数据库类型支持、...