Apache概述

Apache是目前世界上使用最为广泛的一种Web Server,它以跨平台、高效和稳定而闻名。按照去年官方统计的数据,Apache服务器的装机量占该市场60%以上的份额。尤其是在 X(Unix/Linux)平台上,Apache是最常见的选择。其它的Web Server产品,比如IIS,只能运行在Windows平台上,是基于微软.Net架构技术的不二选择。

Apache支持许多特性,大部分通过模块扩展实现。常见的模块包括mod_auth(权限验证)、mod_ssl(SSL和TLS支持) mod_rewrite(URL重写)等。一些通用的语言也支持以Apache模块的方式与Apache集成。 如Perl,Python,Tcl,和PHP等。

Apache并不是没有缺点,它最为诟病的一点就是变得越来越重,被普遍认为是重量级的WebServer。所以,近年来又涌现出了很多轻量级的替 代产品,比如lighttpd,nginx等等,这些WebServer的优点是运行效率很高,但缺点也很明显,成熟度往往要低于Apache,通常只能 用于某些特定场合。

Apache组件逻辑图

Apache是基于模块化设计的,总体上看起来代码的可读性高于php的代码,它的核心代码并不多,大多数的功能都被分散到各个模块中,各个模块在 系统启动的时候按需载入。你如果想要阅读Apache的源代码,建议你直接从main.c文件读起,系统最主要的处理逻辑都包含在里面。

MPM(Multi -Processing Modules,多重处理模块)是Apache的核心组件之一,Apache通过MPM来使用操作系 统的资源,对进程和线程池进行管理。Apache为了能够获得最好的运行性能,针对不同的平台(Unix/Linux、Window)做了优化,为不同的 平台提供了不同的MPM,用户可以根据实际情况进行选择,其中最常使用的MPM有prefork和worker两种。至于您的服务器正以哪种方式运行,取 决于安装Apache过程中指定的MPM编译参数,在X系统上默认的编译参数为prefork。由于大多数的Unix都不支持真正的线程,所以采用了预派 生子进程(prefork)方式,象Windows或者Solaris这些支持线程的平台,基于多进程多线程混合的worker模式是一种不错的选择。对 此感兴趣的同学可以阅读有关资料,此处不再多讲。Apache中还有一个重要的组件就是APR(Apache portable Runtime Library),即Apache可移植运行库,它是一个对操作系统调用的抽象库,用来实现Apache内部组件对操作系统的使用,提高系统的可移植性。 Apache对于php的解析,就是通过众多Module中的php Module来完成的。

Apache的逻辑构成以及与操作系统的关系

PHP与Apache

当PHP需要在Apache服务器下运行时,一般来说,它可以mod_php5模块的形式集成, 此时mod_php5模块的作用是接收Apache传递过来的PHP文件请求,并处理这些请求, 然后将处理后的结果返回给Apache。如果我们在Apache启动前在其配置文件中配置好了PHP模块(mod_php5), PHP模块通过注册apache2的ap_hook_post_config挂钩,在Apache启动的时候启动此模块以接受PHP文件的请求。

除了这种启动时的加载方式,Apache的模块可以在运行的时候动态装载, 这意味着对服务器可以进行功能扩展而不需要重新对源代码进行编译,甚至根本不需要停止服务器。 我们所需要做的仅仅是给服务器发送信号HUP或者AP_SIG_GRACEFUL通知服务器重新载入模块。 但是在动态加载之前,我们需要将模块编译成为动态链接库。此时的动态加载就是加载动态链接库。 Apache中对动态链接库的处理是通过模块mod_so来完成的,因此mod_so模块不能被动态加载, 它只能被静态编译进Apache的核心。这意味着它是随着Apache一起启动的。

Apache是如何加载模块的呢?我们以前面提到的mod_php5模块为例。 首先我们需要在Apache的配置文件httpd.conf中添加一行:

1 LoadModule php5_module modules/mod_php5.so

这里我们使用了LoadModule命令,该命令的第一个参数是模块的名称,名称可以在模块实现的源码中找到。 第二个选项是该模块所处的路径。如果需要在服务器运行时加载模块, 可以通过发送信号HUP或者AP_SIG_GRACEFUL给服务器,一旦接受到该信号,Apache将重新装载模块, 而不需要重新启动服务器。

在配置文件中添加了所上所示的指令后,Apache在加载模块时会根据模块名查找模块并加载, 对于每一个模块,Apache必须保证其文件名是以“mod_”开始的,如PHP的mod_php5.c。 如果命名格式不对,Apache将认为此模块不合法。Apache的每一个模块都是以module结构体的形式存在, module结构的name属性在最后是通过宏STANDARD20_MODULE_STUFF以__FILE__体现。 关于这点可以在后面介绍mod_php5模块时有看到。这也就决定了我们的文件名和模块名是相同的。 通过之前指令中指定的路径找到相关的动态链接库文件后,Apache通过内部的函数获取动态链接库中的内容, 并将模块的内容加载到内存中的指定变量中。

在真正激活模块之前,Apache会检查所加载的模块是否为真正的Apache模块, 这个检测是通过检查module结构体中的magic字段实现的。 而magic字段是通过宏STANDARD20_MODULE_STUFF体现,在这个宏中magic的值为MODULE_MAGIC_COOKIE, MODULE_MAGIC_COOKIE定义如下:

1 #define MODULE_MAGIC_COOKIE 0x41503232UL /* "AP22" */

最后Apache会调用相关函数(ap_add_loaded_module)将模块激活, 此处的激活就是将模块放入相应的链表中(ap_top_modules链表: ap_top_modules链表用来保存Apache中所有的被激活的模块,包括默认的激活模块和激活的第三方模块。)

7.PHP内核探索:Apache模块介绍的更多相关文章

  1. php内核探索 [转]

    PHP内核探索:从SAPI接口开始 PHP内核探索:一次请求的开始与结束 PHP内核探索:一次请求生命周期 PHP内核探索:单进程SAPI生命周期 PHP内核探索:多进程/线程的SAPI生命周期 PH ...

  2. PHP内核探索:哈希碰撞攻击是什么?

    最近哈希表碰撞攻击(Hashtable collisions as DOS attack)的话题不断被提起,各种语言纷纷中招.本文结合PHP内核源码,聊一聊这种攻击的原理及实现. 哈希表碰撞攻击的基本 ...

  3. PHP服务器脚本 PHP内核探索:新垃圾回收机制说明

    在5.2及更早版本的PHP中,没有专门的垃圾回收器GC(Garbage Collection),引擎在判断一个变量空间是否能够被释放的时候是依据这个变量的zval的refcount的值,如果refco ...

  4. 《PHP内核探索系列文章》系列分享专栏

    <PHP内核探索系列文章>已整理成PDF文档,点击可直接下载至本地查阅 简介 PHP内核探索系列文章收藏夹收藏有关PHP内核方面的知识的文章,对PHP高级进阶的朋友提供PHP内核方面的知识 ...

  5. apache常用模块介绍

      mod_actions 基于媒体类型或请求方法,为执行CGI脚本而提供 mod_alias 提供从文件系统的不同部分到文档树的映射和URL重定向 mod_asis 发送自己包含HTTP头内容的文件 ...

  6. PHP内核探索之变量(5)- session的基本原理

    这次说说session. session可以说是当前互联网提到的最多的名词之一了.它的含义很宽泛,可以指任何一次完整的事务交互(会话):如发送一次HTTP请求并接受响应,执行一条SQL语句都可以看做一 ...

  7. PHP内核探索之变量(4)- 数组操作

    上一节(PHP内核探索之变量(3)- hash table),我们已经知道,数组在PHP的底层实际上是HashTable(链接法解决冲突),本文将对最常用的函数系列-数组操作的相关函数做进一步的跟踪. ...

  8. PHP内核探索之变量(3)- hash table

    在PHP中,除了zval, 另一个比较重要的数据结构非hash table莫属,例如我们最常见的数组,在底层便是hash table.除了数组,在线程安全(TSRM).GC.资源管理.Global变量 ...

  9. PHP内核探索之变量(2)-理解引用

    本文主要内容: 引论 符号表与zval 引用原理 回到最初的问题 一.引论 很久之前写了一篇关于引用的文章,当时写的寥寥草草,很多原理都没有说清楚.最近在翻阅Derick Rethans(home: ...

随机推荐

  1. 【ACM - 搜索模板】

    [广搜模板] #include <iostream> #include <stdio.h> #include <string.h> #include <que ...

  2. [译] 在Web Forms 中使用ASP.NET Routing

    本文将以最少的代码想你展示一下的效果: 自定义RUL而不依赖于物理文件名. 使用标记或者代码产生基于route 参数的URL . 如何获得标记或者代码路由过来的参数. 创建Routes void Ap ...

  3. android自动更新程序,安装完以后就什么都没有了,没有出现安装成功的界面的问题

    转载自: http://blog.csdn.net/lovexieyuan520/article/details/9250099 在android软件开发中,总是需要更新版本,所以当有新版本开发的时候 ...

  4. CC2540开发板学习笔记(一)——LED点亮

    一.实验内容: 点亮LDE1.2 二.实验原理: 1.电路原理图: 就一个发光二极管串联一个电阻.电阻是为了防止电流过大.利用发光二极管的单向导电性,在P1为高电平是点亮LED,在低电平是熄灭LED. ...

  5. LoadRunner之自定义HTTP请求

    LoadRunner之自定义HTTP请求 性能测试开发脚本时使用的都是同样的模式.对在性能测试规划时指定的典型业务逻辑场景进行录制,形成基本的脚本骨架. 录制脚本后需要对脚本进行编辑,以满足性能测试需 ...

  6. elk是指logstash,elasticsearch,kibana三件套,这三件套可以组成日志分析和监控工具

    Logstash是一个完全开源的工具,他可以对你的日志进行收集.分析,并将其存储供以后使用(如,搜索),您可以使用它.说到搜索,logstash带有一个web界面,搜索和展示所有日志.kibana 也 ...

  7. 系统启动时,spring配置文件解析失败,报”cvc-elt.1: 找不到元素 'beans' 的声明“异常

    现象:spring加载配置文件applicationContext.xml出错,抛出nested exception is og.xml.sax.SAXParseException; lineNumb ...

  8. BFS+模拟 ZOJ 3865 Superbot

    题目传送门 /* BFS+模拟:dp[i][j][p] 表示走到i,j,方向为p的步数为多少: BFS分4种情况入队,最后在终点4个方向寻找最小值:) */ #include <cstdio&g ...

  9. LightOJ1157 LCS Revisited(DP)

    题目求两个字符串s1,s2不同的LCS个数. 经典的求LCS的DP是这样的: LCS[i][j]表示s1[0...i]和s2[0...j]的LCS LCS[i][j]从LCS[i-1][j-1]+1( ...

  10. LightOJ1417 Forwarding Emails(强连通分量+缩点+记忆化搜索)

    题目大概是,每个人收到信息后会把信息发给他认识的一个人如此下去,问一开始要把信息发送给谁这样看到信息的人数最多. 首先找出图中的SCC并记录每个SCC里面的点数,如果传到一个SCC,那么里面的人都可以 ...