深入探討
等等,沒有這麼簡單。以上過程只是個簡略版,讓我們再深入挖掘一下,看看幕後還發生了些什麼。
PHP啟動第一步
不清楚什麼第一第二步是什麼?別擔心,我們接下來詳細討論一下。讓我們先看看第一步,也是最主要的一步。要記住的是,第一步的操作在任何請求到達之前就發生了。
一個典型的MINIT方法如下:
PHP_MINIT_FUNCTION(extension_name){
/* Initialize functions, classes etc */
}
PHP啟動第二步
一、開篇
在開始這個專題之前,先說一點題外話。大多數人學習編程語言的時候,首先關注的是這種語言的語法及其常用函數。我學習C,Java,Php等語言就是按照這樣的方式開始的。一般情況下,這個階段需要一個月左右的時間就會完全掌握,並能基本熟練地使用。對於已有經驗的同學,可能時間更短。其實各種語言的語法和常用函數都差別不大,有很多相通的地方。如果您在學習一種編程語言的時候,拿一些真正的項目任務作為實踐,效果更佳,實踐遠勝於理論。
我們在掌握了一門編程語言之後,又會向兩個方向發展:一個方向是向上延伸,從事系統框架結構的探索;另一方向是向下延伸,從事系統底層方面的研究,我大體畫了一下這個學習演變過程的示意圖。
注:雖然我的形象一直用著“高高手”,但我只是個菜鳥,如有雷同,純屬巧合,歡迎善意拍磚。
php的語法非常簡單,正是它的簡單性,使它成為了當前互聯網第一編程語言。你不需要具備很多的知識就能上手,比如:你學習C語言,就必須非常了解各個變量如何定義,指針如何操作,內存如何創建銷毀等等。再比如:你學習Java語言,就必須具有面向對象(OO)的基礎,就必須清楚是什麼時候需要封裝,什麼時候需要繼承,什麼時候需要多態,要做項目,怎麼還得懂點SSH。Php的大部分使用者可能根本就沒這麼多講究,有的人喜歡面向過程,那你就用面向過程的方式來寫代碼;有的人喜歡面向對象,那你就用面向對象的方式寫代碼。Php的產生緣於互聯網,目前也是互聯網Web2.0第一編程語言。滿足用戶需求永遠是第一位的,可維護性暫且可以放在第二位。我們通常說Web應用永遠是β版的,計劃遠沒有變化快。
我們公司裡有很多phper,我曾經問過他們:“php程序到底是如何被執行的?”,多數人似乎很難說得清楚。這種情況,其實並不奇怪,我曾經拿類似的問題問過Javaer,Javaer的回答也是如此。有的同學會問:“研究這樣的問題有沒有實際意義呢?”我說:“有!”。理解系統的底層,有助於你寫出高效健壯的代碼,你會更清楚程序的代碼到底該怎麼去寫。另外,如果你有志去做php擴展,那就更不必說,責無旁貸。
要回答以上問題,我覺得最好的辦法是閱讀一下php的源碼,從“根”上解決。近來我找了點時間,粗讀了一遍,願意與各位共享。
關於php的底層工作原理,一定繞不開webserver,象apache,lighttpd,nginx,iis等。我這裡就選擇apache為例吧。以下內容將結合apache的源碼、工作原理和擴展來逐步切入php的解析過程。
二、Apache運行機制剖析
l B/S交互過程
浏覽器(Browser)和服務器(Web Server)的交互過程:
1、 浏覽器向服務器發出HTTP請求(Request)。
2、 服務器收到浏覽器的請求數據,經過分析處理,向浏覽器輸出響應數據(Response)。
3、 浏覽器收到服務器的響應數據,經過分析處理,將最終結果顯示在浏覽器中。
下圖是一份浏覽器請求數據和服務器響應數據的快照:
關於浏覽器和服務器數據交互過程非常簡單,很容易理解。我想從事Web開發的人員都很清楚,在此不再贅述,僅供參考。
l Apache概述
Apache是目前世界上使用最為廣泛的一種Web Server,它以跨平台、高效和穩定而聞名。按照去年官方統計的數據,Apache服務器的裝機量占該市場60%以上的份額。尤其是在X(Unix/Linux)平台上,Apache是最常見的選擇。其它的Web Server產品,比如IIS,只能運行在Windows平台上,是基於微軟.Net架構技術的不二選擇。
Apache並不是沒有缺點,它最為诟病的一點就是變得越來越重,被普遍認為是重量級的WebServer。所以,近年來又湧現出了很多輕量級的替代產品,比如lighttpd,nginx等等,這些WebServer的優點是運行效率很高,但缺點也很明顯,成熟度往往要低於Apache,通常只能用於某些特定場合,。
l 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的邏輯構成以及與操作系統的關系
l Apache的生命周期
這一節的內容會與php模塊的載入有關,您可以略微關注一下。以下是Apache的生命周期(prefork模式)示意圖。
這一篇多寫一點內容,主要是今天終於有時間了。最近工作一直比較忙,公司裡一大攤子事情需要處理,哥們首先得賣身混飯吃,其次才能在閒得蛋疼的時候寫一點。閒話少敘,書接上回:
l Apache的生命周期
這一節的內容將會闡述php模塊的載入過程,請參考Apache的生命周期示意圖(prefork模式下)。
Apache的運行分為啟動階段和運行階段。
1. 啟動階段
在啟動階段,Apache主要進行配置文件解析(例如http.conf以及Include指令設定的配置文件等)、模塊加載(例如mod_php.so,mod_perl.so等)和系統資源初始化(例如日志文件、共享內存段等)工作。
在這個階段,Apache為了獲得系統資源最大的使用權限,將以特權用戶root(X系統)或超級管理員administrator(Windows系統)完成啟動。
Apache和“php處理機”的裝配過程就是在這個階段完成的。
“php處理機”就是負責解釋和執行你的php代碼的系統模塊。這個名字是我特意創造的,目的是為了幫助你理解本節的內容,後面的章節還會給出更專業的名稱。
你單獨做過php的安裝配置嗎?
如果你做過類似的工作,下面的內容很容易理解;如果你沒有做過,可以嘗試安裝一下,有助於加深你的理解。不過,我的文章向來深入淺出,我會盡量把這個過程講得更淺顯一些。其實php的安裝非常簡單,如果你很感興趣的話,可以到網上隨便搜一篇安裝指南,按步驟照做就可以了。
把php最終集成到Apache系統中,還需要對Apache進行一些必要的設置。這裡,我們就以php的mod_php5 SAPI運行模式為例進行講解,至於SAPI這個概念後面我們還會詳細講解。
假定我們安裝的版本是Apache2 和 Php5,那麼需要編輯Apache的主配置文件http.conf,在其中加入下面的幾行內容:
Unix/Linux環境下:
LoadModule php5_module modules/mod_php5.so
AddType application/x-httpd-php .php
注:其中modules/mod_php5.so 是X系統環境下mod_php5.so文件的安裝位置。
Windows環境下:
LoadModule php5_module d:/php/php5apache2.dll
AddType application/x-httpd-php .php
注:其中d:/php/php5apache2.dll 是在Windows環境下php5apache2.dll文件的安裝位置。
這兩項配置就是告訴Apache Server,以後收到的Url用戶請求,凡是以php作為後綴,就需要調用php5_module模塊(mod_php5.so/ php5apache2.dll)進行處理。
這個過程可以參考以下的示意圖:
Apache啟動階段的源碼包含在server/main.c中,我整理了一下源碼中的對應關系:
不熟悉unix/linux的同學可能會問so文件(mod_php5.so)是個什麼樣的文件?
unix/linux下,so後綴文件是一個DSO文件,DSO與windows系統下的dll是等價概念,都是把一堆函數封裝在一個二進制文件中。調用它們的進程把它們裝入內存後,會將其映射到自己的地址空間。
DSO全稱為Dynamic Shared Object,即動態共享對象。DLL全稱為Dynamic Link Library 即動態鏈接庫。
Apache 服務器的體系結構的最大特點,就是高度模塊化。如果你為了追求處理效率,可以把這些dso模塊在apache編譯的時候靜態鏈入,這樣會提高Apache 5%左右的處理性能。