APACHE及DSO模塊工作原理詳解
APACHE 及DSO 模塊工作原理詳解Apache HTTP Server(簡稱Apache )是Apache 軟件基金會的一個開放源碼的網(wǎng)頁服務器,可以在大多數(shù)計算機操作系統(tǒng)中運行,由于其多平臺和
APACHE 及DSO 模塊工作原理詳解
Apache HTTP Server(簡稱Apache )是Apache 軟件基金會的一個開放源碼的網(wǎng)頁服務器,可以在大多數(shù)計算機操作系統(tǒng)中運行,由于其多平臺和安全性被廣泛使用,是最流行的Web 服務器端軟件之一。它快速、可靠并且可通過簡單的API 擴展,將Perl/Python等解釋器編譯到服務器中。專職優(yōu)化、域名注冊、網(wǎng)站空間、虛擬主機、服務器托管、vps 主機、服務器租用的中國信息港在這里為你做詳細介紹!
本文闡述如何使用DSO 模塊及其工作原理。
工作原理
DSO 是Dynamic Shared Objects(動態(tài)共享目標)的縮寫,它是現(xiàn)代Unix 派生出來的操作系統(tǒng)都存在著的一種動態(tài)連接機制。它提供了一種在運行時將特殊格式的代碼,在程序 運行需要時,將需要的部分從外存調(diào)入內(nèi)存執(zhí)行的方法。Apache 在1.3以后的版本后開始支持它。因為Apache 早就使用一個模塊概念來擴展它的功能 并且在內(nèi)部使用一個基于調(diào)度的列表來鏈接擴展模塊到Apache 核心模塊. 所以,Apache 早就注定要使用DSO 來在運行時加載它的模塊。
讓我們先來看一下Apache 本身的程序結構:這是一個很復雜的四層結構--每一層構建在下一層之上。
第四層是用Apache 模塊開發(fā)的第三方庫--比如open ssl 一般來說在Apache 的官方發(fā)行版中這層是空的,但是在實際的Apache 結構中這些庫構成的層結構肯定是存在的。
第三層是一些可選的附加功能模塊--如mod_ssl,mod_perl。這一層的每個模塊通常實現(xiàn)的是Apache 的一個獨立的分離的功能而事實上這些模塊沒有一個是必須的,運行一個最小的Apache 不需要任何一個此層的模塊。
第二層是Apache 的基本功能庫-這也是Apache 的核心本質層--這層包括Apache 內(nèi)核,http_core(Apache的核心模 塊), 它們實現(xiàn)了基本HTTP 功能(比如資源處理(通過文件描述符和內(nèi)存段等等),保持預生成(pre-forked) 子進程模型,監(jiān)聽已配置的虛擬服務 器的TCP/IP套接字,傳輸HTTP 請求流到處理進程,處理HTTP 協(xié)議狀態(tài),讀寫緩沖,此外還有附加的許多功能比如URL 和MIME 頭的解析及DSO 的裝載等),也提供了Apache 的應用程序接口(API) (其實Apache 的真正功能還是包含在內(nèi)部模塊中的,為了允許這些模塊完全控制Apache 進程,內(nèi)核必須提供API 接口), 這層也包括了一般性的可用代碼庫(libap) 和實現(xiàn)正則表達式匹配的庫(libregex) 還有就是一個小的操作系統(tǒng) 的抽象庫(libos) 。
最低層是與OS 相關的平臺性應用函數(shù),這些OS 可以是不同現(xiàn)代UNIX 的變種,win32,os/2,MacOS甚至只要是一個POSIX 子系統(tǒng)。
,
圖1 apache模塊功能分層
在這個復雜的程序結構中有趣的部分是---事實上第三層和第四層與第二層之間是松散的連接,而另一方面第三層的模塊間是互相依賴的--因這種結 構造成的顯著影響就是第三層和第四層的代碼不能靜態(tài)地連接到最低層平臺級的代碼上。因此DSO 模式就成了解決它的一種手段。結合DSO 功能,這個結構就變 得很靈活了,可以讓Apache 內(nèi)核(從技術上說應該是mod_so模塊而不是內(nèi)核)在啟動時(而不是安裝時)裝載必要的部分以實現(xiàn)第三層和第四層的功 能。 現(xiàn)代類Unix 的系統(tǒng)都有一種叫動態(tài)共享對象(DSO)的動態(tài)連接/加載的巧妙的機制,從而可以在運行時刻,將編譯成特殊格式的代碼加載到一個可執(zhí)行程序的地址空間。
加載的方法通常有兩種:其一是,在可執(zhí)行文件啟動時由系統(tǒng)程序ld.so 自動加載;其二是,在執(zhí)行程序中手工地通過Unix 加載器的系統(tǒng)接口執(zhí)行系統(tǒng)調(diào)用dlopen()/dlsym()以實現(xiàn)加載。
按第一種方法,DSO 通常被稱為共享庫(shared libraries) 或者DSO 庫(DSO libraries) ,使用libfoo.so 或者libfoo.so.1.2的文件名,被存儲在系統(tǒng)目錄中(通常是/usr/lib),并在編譯安裝 時,使用連接器參數(shù)-lfoo 建立了指向可執(zhí)行程序的連接。通過設置連接器參數(shù)-R 或者環(huán)境變量LD_LIBRARY_PATH,庫中硬編碼了可執(zhí)行文件 的路徑,使Unix 加載器能夠定位到位于/usr/lib的libfoo.so ,以解析可執(zhí)行文件中尚未解析的位于DSO 的符號。
通常,DSO 不會引用可執(zhí)行文件中的符號(因為它是通用代碼的可重用庫) ,也不會有后繼的解析動作。可執(zhí)行文件無須自己作任何動作以使用DSO 中的符號,而完全由Unix 加載器代辦(事實上,調(diào)用ld.so 的代碼是被連入每個可執(zhí)行文件的非靜態(tài)運行時刻啟動代碼的一部分) 。動態(tài)加載公共庫代碼的 優(yōu)點是明顯
,的:只需要在系統(tǒng)庫libc.so 中存儲一個庫代碼,從而為每個程序節(jié)省了磁盤存儲空間。
按第二種方法,DSO 通常被稱為共享對象(shared objects)或者DSO 文件(DSO files) ,可以使用任何文件名(但是規(guī)范的名稱是foo.so) ,被存儲在程序特定的目錄中,也不會自動建立指向其所用的可執(zhí)行文件的連接,而由可執(zhí) 行文件在運行時自己調(diào)用dlopen()來加載DSO 到其地址空間,同時也不會進行為可執(zhí)行文件解析DSO 中符號的操作。Unix 加載器會根據(jù)可執(zhí)行程序 的輸出符號表和已經(jīng)加載的DSO 庫自動解析DSO 中尚未解析的符號(尤其是無所不在的
libc.so 中的符號) ,如此DSO 就獲得了可執(zhí)行程序的符號信 息,就好象是被靜態(tài)連接的。
最后,為了利用DSO API 的優(yōu)點,執(zhí)行程序必須用dlsym()解析DSO 中的符號,以備稍后在諸如指派表等中使用。也就是說,執(zhí)行程序必須自己解析其所需的符號。這種機制 的優(yōu)點是允許不加載可選的程序部件,直到程序需要的時候才被動態(tài)地加載(也就不需要內(nèi)存開銷) ,以擴展程序的功能。
雖然這種DSO 機制看似很直接,但至少有一個難點,就是在用DSO 擴展程序功能(即第二種方法) 時為DSO 對可執(zhí)行程序中符號的解析,這是因 為,“反向解析”可執(zhí)行程序中的DSO 符號在所有標準平臺上與庫的設計都是矛盾的(庫不會知道什么程序會使用它) 。實際應用中,可執(zhí)行文件中的全局符號通 常不是重輸出的,因此不能為DSO 所用。所以在運行時刻用DSO 來擴展程序功能,就必須找到強制連接器輸出所有全局符號的方法。
共享庫是一種典型的解決方法,因為它符合DSO 機制,而且為操作系統(tǒng)所提供的幾乎所有類型的庫所使用。另一方面,使用共享對象并不是許多程序為擴展其功能所采用的方法。
截止到1998年,只有少數(shù)軟件包使用DSO 機制在運行時刻實際地擴展其功能,諸如Perl 5(通過其XS 機制和DynaLoader 模塊), Netscape Server 等。從
1.3版本開始,Apache 也加入此列,因為Apache 已經(jīng)用了基于指派表
(dispatch-list-based)的方法來連 接外部模塊到Apache 的核心。所以,Apache 也就當然地在運行時刻用DSO 來加載其模塊。
優(yōu)點和缺點
上述基于DSO 的功能有如下優(yōu)點:
由于服務器包的裝配工作可以在運行時刻使用httpd.conf 的配置命令
LoadModule 來進行,而不是在編譯中使用configure 來進行,因此顯得更靈活。比如:只需要安裝一個Apache ,就可以運行多個不同的服務器實例(如標準&SSL版本,濃縮的&功能加強版 本[mod_perl, PHP3],等等) 。
,服務器包可以在安裝后使用第三方模塊被輕易地擴展。這至少對廠商發(fā)行包的維護者有巨大的好處,他可以建立一個Apache 核心包,而為諸如PHP3, mod_perl, mod_fastcgi等擴展另建附加的包。
更簡單的Apache 模塊原型。使用DSO 配合apxs ,可以脫離Apache 源代碼樹,僅需要一個apxs -i 和一個apachectl restart 命令,把開發(fā)的模塊新版本納入運行中的Apache 服務器。
DSO 有如下缺點:
由于并不是所有的操作系統(tǒng)都支持動態(tài)加載代碼到一個程序的地址空間,因此DSO 機制并不能用于所有的平臺。
由于Unix 加載器有必須進行的符號解析的開銷,服務器的啟動會慢20左右。
在某些平臺上,獨立位置代碼(positon independent code[PIC])有時需要復雜的匯編語言技巧來實現(xiàn)相對尋址,而絕對尋址則不需要,因此服務器在運行時會慢5左右。
由于DSO 模塊不能在所有平臺上為其他基于DSO 的庫所連接(ld -lfoo) ,比如,基于a.out 的平臺通常不提供此功能,而基于ELF 的平臺則提供,因此DSO 機制并不能被用于所有類型的模塊?;蛘呖梢赃@樣說,編 譯為DSO 文件的模塊只能使用由Apache 核心、C 庫(libc)和Apache 核心所用的所有其他動態(tài)或靜態(tài)的庫、含有獨立位置代碼的靜態(tài)庫 (libfoo.a)所提供的符號。而要使用其他代碼,就只能確保Apache 核心本身包含對此代碼的引用,或者自己用dlopen()來加載此代碼。
模塊實現(xiàn)
相關模塊 相關指令
mod_so
LoadModule
Apache 對獨立模塊的DSO 支持是建立在被靜態(tài)編譯進Apache 核心的mod_so模塊基礎上的,這是core 以外唯一不能作為DSO 存 在的模塊,而其他所有已發(fā)布的Apache 模塊,都可以通過安裝文檔中闡述的配置選項
--enable-module=shared,被獨立地編譯成 DSO并使之生效。一個被編譯為mod_foo.so的DSO 模塊,可以在httpd.conf 中使用mod_so的LoadModule 指令,在服務器 啟動或重新啟動時被加載。
用命令行參數(shù)-l 可以查看已經(jīng)編譯到服務器中的模塊。
,新提供的支持程序apxs(APache eXtenSion) 可以在Apache 源代碼樹以外編譯基于DSO 的模塊,從而簡化Apache DSO模塊的建立過程。其原理很簡單:安裝Apache 時,配置命令make install會安裝Apache C頭文件,并把依賴于平臺的編譯器和連接器參數(shù)傳給apxs 程序,使用戶可以脫離Apache 的發(fā)布源代碼樹編譯其模塊源代碼,而不改變支持DSO 的編譯 器和連接器的參數(shù)。 用法概要
Apache 2.0的DSO 功能簡要說明:
編譯并安裝已發(fā)布的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 以便共享后續(xù)安裝的模塊:
$ ./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
中國信息港是全國十大品牌服務商,專業(yè)虛擬主機, 域名注冊,VPS 主機, 香港虛擬主機, 香港空間, 服務器租用托管, 雙線服務器, 網(wǎng)站空間, 雙線虛擬主機, 純FTP 主機, 虛擬主機, 網(wǎng)站建設。