关于Apache服务器的工作原理解析

关于Apache 服务器的工作原理解析服务器托管对于网站来说是举足轻重的,选择一个好的服务器就直接关系到了网站的发展,服务器的重要性是不言而喻的,那么面对市场上鱼龙混杂的服务器托管商家,我们该如何擦亮

关于Apache 服务器的工作原理解析

服务器托管对于网站来说是举足轻重的,选择一个好的服务器就直接关系到了网站的发展,服务器的重要性是不言而喻的,那么面对市场上鱼龙混杂的服务器托管商家,我们该如何擦亮双眸呢?专职优化、域名注册、网站空间、虚拟主机、服务器托管、vps 主机、服务器租用的中国信息港来为你探究!

首先Apache HTTP 服务器是一个模块化的软件,使管理者可以选择核心中包含的模块以裁剪功能。可以在编译时选择被静态包含进httpd 二进制映象的模块,也可以编译 成独立于主httpd 二进制映象的动态共享对象DSO ,DSO 模块可以在编译服务器之后编译,也可以用Apache 扩展工具(apxs)编译并增加。 本文阐述如何使用DSO 模块及其工作原理。

工作原理

DSO 是Dynamic Shared Objects(动态共享目标)的缩写,它是现代Unix 派生出来的操作系统都存在着的一种动态连接机制。它提供了一种在运行时将特殊格式的代码,在程序 运行需要时,将需要的部分从外存调入内存执行的方法。Apache 在1.3以后的版本后开始支持它。因为Apache 早就使用一个模块概念来扩展它的功能 并且在内部使用一个基于调度的列表来链接扩展模块到Apache 核心模块. 所以,Apache 早就注定要使用DSO 来在运行时加载它的模块。

让我们先来看一下Apache 本身的程序结构:这是一个很复杂的四层结构--每一层构建在下一层之上。

第四层是用Apache 模块开发的第三方库--比如open ssl 一般来说在Apache 的官方发行版中这层是空的,但是在实际的Apache 结构中这些库构成的层结构肯定是存在的。

第三层是一些可选的附加功能模块--如mod_ssl,mod_perl。这一层的每个模块通常实现的是Apache 的一个独立的分离的功能而事实上这些模块没有一个是必须的,运行一个最小的Apache 不需要任何一个此层的模块。

第二层是Apache 的基本功能库-这也是Apache 的核心本质层--这层包括Apache 内核,http_core(Apache的核心模 块), 它们实现了基本HTTP 功能(比如资源处理(通过文件描述符和内存段等等),保持预生成(pre-forked) 子进程模型,监听已配置的虚拟服务 器的TCP/IP套接字,传输HTTP 请求流到处理进程,处理HTTP 协议状态,读写缓冲,此外还有附加的许多功能比如URL 和MIME 头的解析及DSO 的装载等),也提供了Apache 的应用程序接口(API) (其实Apache 的真正功能还是包含在内部模块中的,为了允许这些模块完全控制Apache 进程,内核必须提供API 接口), 这层也包括了一般性的可用代码库(libap) 和实现正则表达式匹配的库(libregex) 还有就是一个小的操作系统 的抽象库(libos) 。

最低层是与OS 相关的平台性应用函数,这些OS 可以是不同现代UNIX 的变种,win32,os/2,MacOS甚至只要是一个POSIX 子系统。

,

图1 apache模块功能分层

在这个复杂的程序结构中有趣的部分是---事实上第三层和第四层与第二层之间是松散的连接,而另一方面第三层的模块间是互相依赖的--因这种结 构造成的显著影响就是第三层和第四层的代码不能静态地连接到最低层平台级的代码上。因此DSO 模式就成了解决它的一种手段。结合DSO 功能,这个结构就变 得很灵活了,可以让Apache 内核(从技术上说应该是mod_so模块而不是内核)在启动时(而不是安装时)装载必要的部分以实现第三层和第四层的功 能。 现代类Unix 的系统都有一种叫动态共享对象(DSO)的动态连接/加载的巧妙的机制,从而可以在运行时刻,将编译成特殊格式的代码加载到一个可执行程序的地址空间。

加载的方法通常有两种:其一是,在可执行文件启动时由系统程序ld.so 自动加载;其二是,在执行程序中手工地通过Unix 加载器的系统接口执行系统调用dlopen()/dlsym()以实现加载。

按第一种方法,DSO 通常被称为共享库(shared libraries) 或者DSO 库(DSO libraries) ,使用libfoo.so 或者libfoo.so.1.2的文件名,被存储在系统目录中(通常是/usr/lib),并在编译安装 时,使用连接器参数-lfoo 建立了指向可执行程序的连接。通过设置连接器参数-R 或者环境变量LD_LIBRARY_PATH,库中硬编码了可执行文件 的路径,使Unix 加载器能够定位到位于/usr/lib的libfoo.so ,以解析可执行文件中尚未解析的位于DSO 的符号。

通常,DSO 不会引用可执行文件中的符号(因为它是通用代码的可重用库) ,也不会有后继的解析动作。可执行文件无须自己作任何动作以使用DSO 中的符号,而完全由Unix 加载器代办(事实上,调用ld.so 的代码是被连入每个可执行文件的非静态运行时刻启动代码的一部分) 。动态加载公共库代码的 优点是明显

,

的:只需要在系统库libc.so 中存储一个库代码,从而为每个程序节省了磁盘存储空间。

按第二种方法,DSO 通常被称为共享对象(shared objects)或者DSO 文件(DSO files) ,可以使用任何文件名(但是规范的名称是foo.so) ,被存储在程序特定的目录中,也不会自动建立指向其所用的可执行文件的连接,而由可执 行文件在运行时自己调用dlopen()来加载DSO 到其地址空间,同时也不会进行为可执行文件解析DSO 中符号的操作。Unix 加载器会根据可执行程序 的输出符号表和已经加载的DSO 库自动解析DSO 中尚未解析的符号(尤其是无所不在的

libc.so 中的符号) ,如此DSO 就获得了可执行程序的符号信 息,就好象是被静态连接的。

最后,为了利用DSO API 的优点,执行程序必须用dlsym()解析DSO 中的符号,以备稍后在诸如指派表等中使用。也就是说,执行程序必须自己解析其所需的符号。这种机制 的优点是允许不加载可选的程序部件,直到程序需要的时候才被动态地加载(也就不需要内存开销) ,以扩展程序的功能。

虽然这种DSO 机制看似很直接,但至少有一个难点,就是在用DSO 扩展程序功能(即第二种方法) 时为DSO 对可执行程序中符号的解析,这是因 为,“反向解析”可执行程序中的DSO 符号在所有标准平台上与库的设计都是矛盾的(库不会知道什么程序会使用它) 。实际应用中,可执行文件中的全局符号通 常不是重输出的,因此不能为DSO 所用。所以在运行时刻用DSO 来扩展程序功能,就必须找到强制连接器输出所有全局符号的方法。

共享库是一种典型的解决方法,因为它符合DSO 机制,而且为操作系统所提供的几乎所有类型的库所使用。另一方面,使用共享对象并不是许多程序为扩展其功能所采用的方法。

截止到1998年,只有少数软件包使用DSO 机制在运行时刻实际地扩展其功能,诸如Perl 5(通过其XS 机制和DynaLoader 模块), Netscape Server 等。从

1.3版本开始,Apache 也加入此列,因为Apache 已经用了基于指派表

(dispatch-list-based)的方法来连 接外部模块到Apache 的核心。所以,Apache 也就当然地在运行时刻用DSO 来加载其模块。

优点和缺点

上述基于DSO 的功能有如下优点:

由于服务器包的装配工作可以在运行时刻使用httpd.conf 的配置命令

LoadModule 来进行,而不是在编译中使用configure 来进行,因此显得更灵活。比如:只需要安装一个Apache ,就可以运行多个不同的服务器实例(如标准&SSL版本,浓缩的&功能加强版 本[mod_perl, PHP3],等等) 。

,

服务器包可以在安装后使用第三方模块被轻易地扩展。这至少对厂商发行包的维护者有巨大的好处,他可以建立一个Apache 核心包,而为诸如PHP3, mod_perl, mod_fastcgi等扩展另建附加的包。

更简单的Apache 模块原型。使用DSO 配合apxs ,可以脱离Apache 源代码树,仅需要一个apxs -i 和一个apachectl restart 命令,把开发的模块新版本纳入运行中的Apache 服务器。

DSO 有如下缺点:

由于并不是所有的操作系统都支持动态加载代码到一个程序的地址空间,因此DSO 机制并不能用于所有的平台。

由于Unix 加载器有必须进行的符号解析的开销,服务器的启动会慢20左右。

在某些平台上,独立位置代码(positon independent code[PIC])有时需要复杂的汇编语言技巧来实现相对寻址,而绝对寻址则不需要,因此服务器在运行时会慢5左右。

由于DSO 模块不能在所有平台上为其他基于DSO 的库所连接(ld -lfoo) ,比如,基于a.out 的平台通常不提供此功能,而基于ELF 的平台则提供,因此DSO 机制并不能被用于所有类型的模块。或者可以这样说,编 译为DSO 文件的模块只能使用由Apache 核心、C 库(libc)和Apache 核心所用的所有其他动态或静态的库、含有独立位置代码的静态库 (libfoo.a)所提供的符号。而要使用其他代码,就只能确保Apache 核心本身包含对此代码的引用,或者自己用dlopen()来加载此代码。

模块实现

相关模块 相关指令

mod_so

LoadModule

Apache 对独立模块的DSO 支持是建立在被静态编译进Apache 核心的mod_so模块基础上的,这是core 以外唯一不能作为DSO 存 在的模块,而其他所有已发布的Apache 模块,都可以通过安装文档中阐述的配置选项

--enable-module=shared,被独立地编译成 DSO并使之生效。一个被编译为mod_foo.so的DSO 模块,可以在httpd.conf 中使用mod_so的LoadModule 指令,在服务器 启动或重新启动时被加载。

用命令行参数-l 可以查看已经编译到服务器中的模块。

,

新提供的支持程序apxs(APache eXtenSion) 可以在Apache 源代码树以外编译基于DSO 的模块,从而简化Apache DSO模块的建立过程。其原理很简单:安装Apache 时,配置命令make install会安装Apache C头文件,并把依赖于平台的编译器和连接器参数传给apxs 程序,使用户可以脱离Apache 的发布源代码树编译其模块源代码,而不改变支持DSO 的编译 器和连接器的参数。 用法概要

Apache 2.0的DSO 功能简要说明:

编译并安装已发布的Apache 模块,比如编译mod_foo.c为mod_foo.so的DSO 模块:

$ ./configure --prefix=/path/to/install --enable-foo=shared $ make install

编译并安装第三方Apache 模块, 比如编译mod_foo.c为mod_foo.so的DSO 模块:

$ ./configure --add-module=module_type:/path/to/3rdparty/mod_foo.c --enable-foo=shared

$ make install

配置Apache 以便共享后续安装的模块:

$ ./configure --enable-so

$ make install

用apxs 在Apache 源代码树以外编译并安装第三方Apache 模块,比如编译mod_foo.c为mod_foo.so的DSO 模块:

$ cd /path/to/3rdparty

$ apxs -c mod_foo.c

$ apxs -i -a -n foo mod_foo.la

中国信息港专业域名注册, 域名申请, 域名查询, 服务器托管,服务器租用, 云主机, 虚拟主机,vps 主机,香港虚拟主机, 企业邮箱, 企业邮局, 企业短信, 邮箱域名, 代理做账,公司代注 , 域名交易, 网站建设, 可信网站, 网站推广, 域名查询, 双线主机, 美国主机, 海外主机, 虚拟主机提供商, 微软SPLA 认证运营商, 虚拟主机管理, 中文域名, 中国域名, 顶级域名注册, 域名注册提供商, 域名服务商, 自定制主机, 动态域名。

标签: