探究php底层运行机制
本文轉(zhuǎn)載自:http://www.myext.cn/Article/921.html
概要
簡(jiǎn)介
先看看下面這個(gè)過(guò)程:
我們從未手動(dòng)開(kāi)啟過(guò)PHP的相關(guān)進(jìn)程,它是隨著Apache的啟動(dòng)而運(yùn)行的;?
php通過(guò)mod_php5.so模塊和Apache相連(具體說(shuō)來(lái)是SAPI,即服務(wù)器應(yīng)用程序編程接口);?
PHP總共有三個(gè)模塊:內(nèi)核、Zend引擎、以及擴(kuò)展層;?
PHP內(nèi)核用來(lái)處理請(qǐng)求、文件流、錯(cuò)誤處理等相關(guān)操作;?
Zend引擎(ZE)用以將源文件轉(zhuǎn)換成機(jī)器語(yǔ)言,然后在虛擬機(jī)上運(yùn)行它;?
擴(kuò)展層是一組函數(shù)、類(lèi)庫(kù)和流,PHP使用它們來(lái)執(zhí)行一些特定的操作。比如,我們需要MySQL擴(kuò)展來(lái)連接mysql數(shù)據(jù)庫(kù);?
當(dāng)ZE執(zhí)行程序時(shí)可能會(huì)需要連接若干擴(kuò)展,這時(shí)ZE將控制權(quán)交給擴(kuò)展,等處理完特定任務(wù)后再返還;
最后,ZE將程序運(yùn)行結(jié)果返回給PHP內(nèi)核,它再將結(jié)果傳送給SAPI層,最終輸出到瀏覽器上。?
深入探討
等等,沒(méi)有這么簡(jiǎn)單。以上過(guò)程只是個(gè)簡(jiǎn)略版,讓我們?cè)偕钊胪诰蛞幌?#xff0c;看看幕后還發(fā)生了些什么。
Apache啟動(dòng)后,PHP解釋程序也隨之啟動(dòng);?
PHP的啟動(dòng)過(guò)程有兩步;?
第一步是初始化一些環(huán)境變量,這將在整個(gè)SAPI生命周期中發(fā)生作用;?
第二步是生成只針對(duì)當(dāng)前請(qǐng)求的一些變量設(shè)置。?
PHP啟動(dòng)第一步
不清楚什么第一第二步是什么?別擔(dān)心,我們接下來(lái)詳細(xì)討論一下。讓我們先看看第一步,也是最主要的一步。要記住的是,第一步的操作在任何請(qǐng)求到達(dá)之前就發(fā)生了。
啟動(dòng)Apache后,PHP解釋程序也隨之啟動(dòng);?
PHP調(diào)用各個(gè)擴(kuò)展的MINIT方法,從而使這些擴(kuò)展切換到可用狀態(tài)。看看php.ini文件里打開(kāi)了哪些擴(kuò)展吧;?
MINIT的意思是“模塊初始化”。各個(gè)模塊都定義了一組函數(shù)、類(lèi)庫(kù)等用以處理其他請(qǐng)求。?
一個(gè)典型的MINIT方法如下:
PHP_MINIT_FUNCTION(extension_name){
/* Initialize functions, classes etc */
}
PHP啟動(dòng)第二步
當(dāng)一個(gè)頁(yè)面請(qǐng)求發(fā)生時(shí),SAPI層將控制權(quán)交給PHP層。于是PHP設(shè)置了用于回復(fù)本次請(qǐng)求所需的環(huán)境變量。同時(shí),它還建立一個(gè)變量表,用來(lái)存放執(zhí)行過(guò)程中產(chǎn)生的變量名和值。?
PHP調(diào)用各個(gè)模塊的RINIT方法,即“請(qǐng)求初始化”。一個(gè)經(jīng)典的例子是Session模塊的RINIT,如果在php.ini中啟用了Session模塊,那在調(diào)用該模塊的RINIT時(shí)就會(huì)初始化$_SESSION變量,并將相關(guān)內(nèi)容讀入;?
RINIT方法可以看作是一個(gè)準(zhǔn)備過(guò)程,在程序執(zhí)行之間就會(huì)自動(dòng)啟動(dòng)。?
一個(gè)典型的RINIT方法如下:
PHP_RINIT_FUNCTION(extension_name) {
/* Initialize session variables, pre-populate variables, redefine global variables etc */
}
PHP關(guān)閉第一步
如同PHP啟動(dòng)一樣,PHP的關(guān)閉也分兩步:
一旦頁(yè)面執(zhí)行完畢(無(wú)論是執(zhí)行到了文件末尾還是用exit或die函數(shù)中止),PHP就會(huì)啟動(dòng)清理程序。它會(huì)按順序調(diào)用各個(gè)模塊的RSHUTDOWN方法。?
RSHUTDOWN用以清除程序運(yùn)行時(shí)產(chǎn)生的符號(hào)表,也就是對(duì)每個(gè)變量調(diào)用unset函數(shù)。?
一個(gè)典型的RSHUTDOWN方法如下:
PHP_RSHUTDOWN_FUNCTION(extension_name) {
/* Do memory management, unset all variables used in the last PHP call etc */
}
PHP關(guān)閉第二步
最后,所有的請(qǐng)求都已處理完畢,SAPI也準(zhǔn)備關(guān)閉了,PHP開(kāi)始執(zhí)行第二步:
PHP調(diào)用每個(gè)擴(kuò)展的MSHUTDOWN方法,這是各個(gè)模塊最后一次釋放內(nèi)存的機(jī)會(huì)。?
一個(gè)典型的RSHUTDOWN方法如下:
PHP_MSHUTDOWN_FUNCTION(extension_name) {
/* Free handlers and persistent memory etc */
}
這樣,整個(gè)PHP生命周期就結(jié)束了。要注意的是,只有在服務(wù)器沒(méi)有請(qǐng)求的情況下才會(huì)執(zhí)行“啟動(dòng)第一步”和“關(guān)閉第二步”。
一、開(kāi)篇
在開(kāi)始這個(gè)專(zhuān)題之前,先說(shuō)一點(diǎn)題外話(huà)。大多數(shù)人學(xué)習(xí)編程語(yǔ)言的時(shí)候,首先關(guān)注的是這種語(yǔ)言的語(yǔ)法及其常用函數(shù)。我學(xué)習(xí)C,Java,Php等語(yǔ)言就是按照這樣的方式開(kāi)始的。一般情況下,這個(gè)階段需要一個(gè)月左右的時(shí)間就會(huì)完全掌握,并能基本熟練地使用。對(duì)于已有經(jīng)驗(yàn)的同學(xué),可能時(shí)間更短。其實(shí)各種語(yǔ)言的語(yǔ)法和常用函數(shù)都差別不大,有很多相通的地方。如果您在學(xué)習(xí)一種編程語(yǔ)言的時(shí)候,拿一些真正的項(xiàng)目任務(wù)作為實(shí)踐,效果更佳,實(shí)踐遠(yuǎn)勝于理論。
我們?cè)谡莆樟艘婚T(mén)編程語(yǔ)言之后,又會(huì)向兩個(gè)方向發(fā)展:一個(gè)方向是向上延伸,從事系統(tǒng)框架結(jié)構(gòu)的探索;另一方向是向下延伸,從事系統(tǒng)底層方面的研究,我大體畫(huà)了一下這個(gè)學(xué)習(xí)演變過(guò)程的示意圖。
?
?
?
注:雖然我的形象一直用著“高高手”,但我只是個(gè)菜鳥(niǎo),如有雷同,純屬巧合,歡迎善意拍磚。
?
php的語(yǔ)法非常簡(jiǎn)單,正是它的簡(jiǎn)單性,使它成為了當(dāng)前互聯(lián)網(wǎng)第一編程語(yǔ)言。你不需要具備很多的知識(shí)就能上手,比如:你學(xué)習(xí)C語(yǔ)言,就必須非常了解各個(gè)變量如何定義,指針如何操作,內(nèi)存如何創(chuàng)建銷(xiāo)毀等等。再比如:你學(xué)習(xí)Java語(yǔ)言,就必須具有面向?qū)ο?OO)的基礎(chǔ),就必須清楚是什么時(shí)候需要封裝,什么時(shí)候需要繼承,什么時(shí)候需要多態(tài),要做項(xiàng)目,怎么還得懂點(diǎn)SSH。Php的大部分使用者可能根本就沒(méi)這么多講究,有的人喜歡面向過(guò)程,那你就用面向過(guò)程的方式來(lái)寫(xiě)代碼;有的人喜歡面向?qū)ο?#xff0c;那你就用面向?qū)ο蟮姆绞綄?xiě)代碼。Php的產(chǎn)生緣于互聯(lián)網(wǎng),目前也是互聯(lián)網(wǎng)Web2.0第一編程語(yǔ)言。滿(mǎn)足用戶(hù)需求永遠(yuǎn)是第一位的,可維護(hù)性暫且可以放在第二位。我們通常說(shuō)Web應(yīng)用永遠(yuǎn)是β版的,計(jì)劃遠(yuǎn)沒(méi)有變化快。
我們公司里有很多phper,我曾經(jīng)問(wèn)過(guò)他們:“php程序到底是如何被執(zhí)行的?”,多數(shù)人似乎很難說(shuō)得清楚。這種情況,其實(shí)并不奇怪,我曾經(jīng)拿類(lèi)似的問(wèn)題問(wèn)過(guò)Javaer,Javaer的回答也是如此。有的同學(xué)會(huì)問(wèn):“研究這樣的問(wèn)題有沒(méi)有實(shí)際意義呢?”我說(shuō):“有!”。理解系統(tǒng)的底層,有助于你寫(xiě)出高效健壯的代碼,你會(huì)更清楚程序的代碼到底該怎么去寫(xiě)。另外,如果你有志去做php擴(kuò)展,那就更不必說(shuō),責(zé)無(wú)旁貸。
要回答以上問(wèn)題,我覺(jué)得最好的辦法是閱讀一下php的源碼,從“根”上解決。近來(lái)我找了點(diǎn)時(shí)間,粗讀了一遍,愿意與各位共享。
關(guān)于php的底層工作原理,一定繞不開(kāi)webserver,象apache,lighttpd,nginx,iis等。我這里就選擇apache為例吧。以下內(nèi)容將結(jié)合apache的源碼、工作原理和擴(kuò)展來(lái)逐步切入php的解析過(guò)程。
?
?
二、Apache運(yùn)行機(jī)制剖析
l???????? B/S交互過(guò)程
瀏覽器(Browser)和服務(wù)器(Web Server)的交互過(guò)程:
?
?
?
1、? 瀏覽器向服務(wù)器發(fā)出HTTP請(qǐng)求(Request)。
2、? 服務(wù)器收到瀏覽器的請(qǐng)求數(shù)據(jù),經(jīng)過(guò)分析處理,向?yàn)g覽器輸出響應(yīng)數(shù)據(jù)(Response)。
3、? 瀏覽器收到服務(wù)器的響應(yīng)數(shù)據(jù),經(jīng)過(guò)分析處理,將最終結(jié)果顯示在瀏覽器中。
?下圖是一份瀏覽器請(qǐng)求數(shù)據(jù)和服務(wù)器響應(yīng)數(shù)據(jù)的快照:
?
?
關(guān)于瀏覽器和服務(wù)器數(shù)據(jù)交互過(guò)程非常簡(jiǎn)單,很容易理解。我想從事Web開(kāi)發(fā)的人員都很清楚,在此不再贅述,僅供參考。
?
l???????? Apache概述
Apache是目前世界上使用最為廣泛的一種Web Server,它以跨平臺(tái)、高效和穩(wěn)定而聞名。按照去年官方統(tǒng)計(jì)的數(shù)據(jù),Apache服務(wù)器的裝機(jī)量占該市場(chǎng)60%以上的份額。尤其是在X(Unix/Linux)平臺(tái)上,Apache是最常見(jiàn)的選擇。其它的Web Server產(chǎn)品,比如IIS,只能運(yùn)行在Windows平臺(tái)上,是基于微軟.Net架構(gòu)技術(shù)的不二選擇。
Apache并不是沒(méi)有缺點(diǎn),它最為詬病的一點(diǎn)就是變得越來(lái)越重,被普遍認(rèn)為是重量級(jí)的WebServer。所以,近年來(lái)又涌現(xiàn)出了很多輕量級(jí)的替代產(chǎn)品,比如lighttpd,nginx等等,這些WebServer的優(yōu)點(diǎn)是運(yùn)行效率很高,但缺點(diǎn)也很明顯,成熟度往往要低于Apache,通常只能用于某些特定場(chǎng)合,。
?
l???????? Apache組件邏輯圖
Apache是基于模塊化設(shè)計(jì)的,總體上看起來(lái)代碼的可讀性高于php的代碼,它的核心代碼并不多,大多數(shù)的功能都被分散到各個(gè)模塊中,各個(gè)模塊在系統(tǒng)啟動(dòng)的時(shí)候按需載入。你如果想要閱讀Apache的源代碼,建議你直接從main.c文件讀起,系統(tǒng)最主要的處理邏輯都包含在里面。MPM(Multi?-Processing?Modules,多重處理模塊)是Apache的核心組件之一,Apache通過(guò)MPM來(lái)使用操作系統(tǒng)的資源,對(duì)進(jìn)程和線程池進(jìn)行管理。Apache為了能夠獲得最好的運(yùn)行性能,針對(duì)不同的平臺(tái)(Unix/linux、Window)做了優(yōu)化,為不同的平臺(tái)提供了不同的MPM,用戶(hù)可以根據(jù)實(shí)際情況進(jìn)行選擇,其中最常使用的MPM有prefork和worker兩種。至于您的服務(wù)器正以哪種方式運(yùn)行,取決于安裝Apache過(guò)程中指定的MPM編譯參數(shù),在X系統(tǒng)上默認(rèn)的編譯參數(shù)為prefork。由于大多數(shù)的Unix都不支持真正的線程,所以采用了預(yù)派生子進(jìn)程(prefork)方式,象Windows或者Solaris這些支持線程的平臺(tái),基于多進(jìn)程多線程混合的worker模式是一種不錯(cuò)的選擇。對(duì)此感興趣的同學(xué)可以閱讀有關(guān)資料,此處不再多講。Apache中還有一個(gè)重要的組件就是APR(Apache portable Runtime Library),即Apache可移植運(yùn)行庫(kù),它是一個(gè)對(duì)操作系統(tǒng)調(diào)用的抽象庫(kù),用來(lái)實(shí)現(xiàn)Apache內(nèi)部組件對(duì)操作系統(tǒng)的使用,提高系統(tǒng)的可移植性。Apache對(duì)于php的解析,就是通過(guò)眾多Module中的php Module來(lái)完成的。
?
?
Apache的邏輯構(gòu)成以及與操作系統(tǒng)的關(guān)系
?
l???????? Apache的生命周期
這一節(jié)的內(nèi)容會(huì)與php模塊的載入有關(guān),您可以略微關(guān)注一下。以下是Apache的生命周期(prefork模式)示意圖。
?
?
?
?
l???????? Apache的生命周期
這一節(jié)的內(nèi)容將會(huì)闡述php模塊的載入過(guò)程,請(qǐng)參考Apache的生命周期示意圖(prefork模式下)。
?
Apache的運(yùn)行分為啟動(dòng)階段和運(yùn)行階段。
?
1.???????? 啟動(dòng)階段
在啟動(dòng)階段,Apache主要進(jìn)行配置文件解析(例如http.conf以及Include指令設(shè)定的配置文件等)、模塊加載(例如mod_php.so,mod_perl.so等)和系統(tǒng)資源初始化(例如日志文件、共享內(nèi)存段等)工作。
在這個(gè)階段,Apache為了獲得系統(tǒng)資源最大的使用權(quán)限,將以特權(quán)用戶(hù)root(X系統(tǒng))或超級(jí)管理員administrator(Windows系統(tǒng))完成啟動(dòng)。
?
Apache和“php處理機(jī)”的裝配過(guò)程就是在這個(gè)階段完成的。
“php處理機(jī)”就是負(fù)責(zé)解釋和執(zhí)行你的php代碼的系統(tǒng)模塊。這個(gè)名字是我特意創(chuàng)造的,目的是為了幫助你理解本節(jié)的內(nèi)容,后面的章節(jié)還會(huì)給出更專(zhuān)業(yè)的名稱(chēng)。
?
你單獨(dú)做過(guò)php的安裝配置嗎?
如果你做過(guò)類(lèi)似的工作,下面的內(nèi)容很容易理解;如果你沒(méi)有做過(guò),可以嘗試安裝一下,有助于加深你的理解。不過(guò),我的文章向來(lái)深入淺出,我會(huì)盡量把這個(gè)過(guò)程講得更淺顯一些。其實(shí)php的安裝非常簡(jiǎn)單,如果你很感興趣的話(huà),可以到網(wǎng)上隨便搜一篇安裝指南,按步驟照做就可以了。
把php最終集成到Apache系統(tǒng)中,還需要對(duì)Apache進(jìn)行一些必要的設(shè)置。這里,我們就以php的mod_php5 SAPI運(yùn)行模式為例進(jìn)行講解,至于SAPI這個(gè)概念后面我們還會(huì)詳細(xì)講解。
假定我們安裝的版本是Apache2 和 Php5,那么需要編輯Apache的主配置文件http.conf,在其中加入下面的幾行內(nèi)容:
Unix/Linux環(huán)境下:
LoadModule php5_module modules/mod_php5.so
AddType application/x-httpd-php .php
注:其中modules/mod_php5.so 是X系統(tǒng)環(huán)境下mod_php5.so文件的安裝位置。
?
Windows環(huán)境下:
LoadModule php5_module d:/php/php5apache2.dll
AddType application/x-httpd-php .php
注:其中d:/php/php5apache2.dll 是在Windows環(huán)境下php5apache2.dll文件的安裝位置。
這兩項(xiàng)配置就是告訴Apache Server,以后收到的Url用戶(hù)請(qǐng)求,凡是以php作為后綴,就需要調(diào)用php5_module模塊(mod_php5.so/ php5apache2.dll)進(jìn)行處理。
?
這個(gè)過(guò)程可以參考以下的示意圖:
?
?
?
Apache啟動(dòng)階段的源碼包含在server/main.c中,我整理了一下源碼中的對(duì)應(yīng)關(guān)系:
?
?
?
?
不熟悉unix/linux的同學(xué)可能會(huì)問(wèn)so文件(mod_php5.so)是個(gè)什么樣的文件?
unix/linux下,so后綴文件是一個(gè)DSO文件,DSO與windows系統(tǒng)下的dll是等價(jià)概念,都是把一堆函數(shù)封裝在一個(gè)二進(jìn)制文件中。調(diào)用它們的進(jìn)程把它們裝入內(nèi)存后,會(huì)將其映射到自己的地址空間。
DSO全稱(chēng)為Dynamic Shared Object,即動(dòng)態(tài)共享對(duì)象。DLL全稱(chēng)為Dynamic Link Library 即動(dòng)態(tài)鏈接庫(kù)。
Apache 服務(wù)器的體系結(jié)構(gòu)的最大特點(diǎn),就是高度模塊化。如果你為了追求處理效率,可以把這些dso模塊在apache編譯的時(shí)候靜態(tài)鏈入,這樣會(huì)提高Apache 5%左右的處理性能。
?
2.???????? 運(yùn)行階段
在運(yùn)行階段,Apache主要工作是處理用戶(hù)的服務(wù)請(qǐng)求。
在這個(gè)階段,Apache放棄特權(quán)用戶(hù)級(jí)別,使用普通權(quán)限,這主要是基于安全性的考慮,防止由于代碼的缺陷引起的安全漏洞,象微軟的IIS就曾遭受“紅色代碼(Code Red)”和“尼姆達(dá)(Nimda)”等惡意代碼的溢出攻擊。
?
?
2、運(yùn)行階段
???? 2.1 運(yùn)行階段概述
??? 在運(yùn)行階段,Apache主要工作是處理用戶(hù)的服務(wù)請(qǐng)求。
??? 在這個(gè)階段,Apache放棄特權(quán)用戶(hù)級(jí)別,使用普通權(quán)限,這主要是基于安全性的考慮,防止由于代碼的缺陷引起的安全漏洞。象微軟的IIS就曾遭受“紅色代碼(Code Red)”和“尼姆達(dá)(Nimda)”等惡意代碼的溢出攻擊。
?
??2.2 運(yùn)行階段流程
??? Apache將請(qǐng)求處理循環(huán)分為11個(gè)階段,依次是:Post-Read-Request,URI Translation,Header Parsing,Access Control,Authentication,Authorization,MIME Type Checking,FixUp,Response,Logging,CleanUp。
?
?
???? Apache Hook機(jī)制
???? Apache的Hook機(jī)制是指:Apache 允許模塊(包括內(nèi)部模塊和外部模塊,例如mod_php5.so,mod_perl.so等)將自定義的函數(shù)注入到請(qǐng)求處理循環(huán)中。換句話(huà)說(shuō),模塊可以在Apache的任何一個(gè)處理階段中掛接(Hook)上自己的處理函數(shù),從而參與Apache的請(qǐng)求處理過(guò)程。
??? mod_php5.so/ php5apache2.dll就是將所包含的自定義函數(shù),通過(guò)Hook機(jī)制注入到Apache中,在Apache處理流程的各個(gè)階段負(fù)責(zé)處理php請(qǐng)求。
??? 關(guān)于Hook機(jī)制在Windows系統(tǒng)開(kāi)發(fā)也經(jīng)常遇到,在Windows開(kāi)發(fā)既有系統(tǒng)級(jí)的鉤子,又有應(yīng)用級(jí)的鉤子。常見(jiàn)的翻譯軟件(例如金山詞霸等等)的屏幕取詞功能,大多數(shù)是通過(guò)安裝系統(tǒng)級(jí)鉤子函數(shù)完成的,將自定義函數(shù)替換gdi32.dll中的屏幕輸出的繪制函數(shù)。
?
??? Apache請(qǐng)求處理循環(huán)詳解
??? Apache請(qǐng)求處理循環(huán)的11個(gè)階段都做了哪些事情呢?
???
??? 1、Post-Read-Request階段
??? 在正常請(qǐng)求處理流程中,這是模塊可以插入鉤子的第一個(gè)階段。對(duì)于那些想很早進(jìn)入處理請(qǐng)求的模塊來(lái)說(shuō),這個(gè)階段可以被利用。
??? 2、URI Translation階段
??? Apache在本階段的主要工作:將請(qǐng)求的URL映射到本地文件系統(tǒng)。模塊可以在這階段插入鉤子,執(zhí)行自己的映射邏輯。mod_alias就是利用這個(gè)階段工作的。
??? 3、Header Parsing階段
??? Apache在本階段的主要工作:檢查請(qǐng)求的頭部。由于模塊可以在請(qǐng)求處理流程的任何一個(gè)點(diǎn)上執(zhí)行檢查請(qǐng)求頭部的任務(wù),因此這個(gè)鉤子很少被使用。mod_setenvif就是利用這個(gè)階段工作的。
?
??? 4、Access Control階段
??? Apache在本階段的主要工作:根據(jù)配置文件檢查是否允許訪問(wèn)請(qǐng)求的資源。Apache的標(biāo)準(zhǔn)邏輯實(shí)現(xiàn)了允許和拒絕指令。mod_authz_host就是利用這個(gè)階段工作的。
??? 5、Authentication階段
???? Apache在本階段的主要工作:按照配置文件設(shè)定的策略對(duì)用戶(hù)進(jìn)行認(rèn)證,并設(shè)定用戶(hù)名區(qū)域。模塊可以在這階段插入鉤子,實(shí)現(xiàn)一個(gè)認(rèn)證方法。
?
??? 6、Authorization階段
??? Apache在本階段的主要工作:根據(jù)配置文件檢查是否允許認(rèn)證過(guò)的用戶(hù)執(zhí)行請(qǐng)求的操作。模塊可以在這階段插入鉤子,實(shí)現(xiàn)一個(gè)用戶(hù)權(quán)限管理的方法。
??? 7、MIME Type Checking階段
??? Apache在本階段的主要工作:根據(jù)請(qǐng)求資源的MIME類(lèi)型的相關(guān)規(guī)則,判定將要使用的內(nèi)容處理函數(shù)。標(biāo)準(zhǔn)模塊mod_negotiation和mod_mime實(shí)現(xiàn)了這個(gè)鉤子。
??? 8、FixUp階段
??? 這是一個(gè)通用的階段,允許模塊在內(nèi)容生成器之前,運(yùn)行任何必要的處理流程。和Post_Read_Request類(lèi)似,這是一個(gè)能夠捕獲任何信息的鉤子,也是最常使用的鉤子。
??? 9、Response階段
??? Apache在本階段的主要工作:生成返回客戶(hù)端的內(nèi)容,負(fù)責(zé)給客戶(hù)端發(fā)送一個(gè)恰當(dāng)?shù)幕貜?fù)。這個(gè)階段是整個(gè)處理流程的核心部分。
??? 10、Logging階段
??? Apache在本階段的主要工作:在回復(fù)已經(jīng)發(fā)送給客戶(hù)端之后記錄事務(wù)。模塊可能修改或者替換Apache的標(biāo)準(zhǔn)日志記錄。
?
??? 11、CleanUp階段
??? Apache在本階段的主要工作:清理本次請(qǐng)求事務(wù)處理完成之后遺留的環(huán)境,比如文件、目錄的處理或者Socket的關(guān)閉等等,這是Apache一次請(qǐng)求處理的最后一個(gè)階段。
?
??? 模塊的注入Apache的過(guò)程可以參考源碼中server/core.c文件:
?
??? mod_php5.so/ php5apache2.dll注入到Apache的函數(shù)中,最重要的就是Response階段的處理函數(shù)。
來(lái)源:http://blog.csdn.net/shupan001/article/details/7176169
總結(jié)
以上是生活随笔為你收集整理的探究php底层运行机制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 贾玲个人资料(贾玲丈夫资料)
- 下一篇: 白马非马的哲学原理矛盾(白马非马的哲学原