1. 程式人生 > >apache-php底層工作原理

apache-php底層工作原理

先看看下面這個過程:

  • 我們從未手動開啟過PHP的相關程序,它是隨著Apache的啟動而執行的;
  • PHP通過mod_php5.so模組和Apache相連(具體說來是SAPI,即伺服器應用程式程式設計介面);
  • PHP總共有三個模組:核心、Zend引擎、以及擴充套件層;
  • PHP核心用來處理請求、檔案流、錯誤處理等相關操作;
  • Zend引擎(ZE)用以將原始檔轉換成機器語言,然後在虛擬機器上執行它;
  • 擴充套件層是一組函式、類庫和流,PHP使用它們來執行一些特定的操作。比如,我們需要mysql擴充套件來連線MySQL資料庫;
  • 當ZE執行程式時可能會需要連線若干擴充套件,這時ZE將控制權交給擴充套件,等處理完特定任務後再返還;
  • 最後,ZE將程式執行結果返回給PHP核心,它再將結果傳送給SAPI層,最終輸出到瀏覽器上。

深入探討

  • Apache啟動後,PHP解釋程式也隨之啟動;
  • PHP的啟動過程有兩步;
  • 第一步是初始化一些環境變數,這將在整個SAPI生命週期中發生作用;
  • 第二步是生成只針對當前請求的一些變數設定。

PHP啟動第一步
  不清楚什麼第一第二步是什麼?別擔心,我們接下來詳細討論一下。讓我們先看看第一步,也是最主要的一步。要記住的是,第一步的操作在任何請求到達之前就發生了。

  • 啟動Apache後,PHP解釋程式也隨之啟動;
  • PHP呼叫各個擴充套件的MINIT方法,從而使這些擴充套件切換到可用狀態。看看php.ini檔案裡打開了哪些擴充套件吧;
  • MINIT的意思是“模組初始化”。各個模組都定義了一組函式、類庫等用以處理其他請求。

  一個典型的MINIT方法如下:
PHP_MINIT_FUNCTION(extension_name){
/* Initialize functions, classes etc */
}
PHP啟動第二步

  • 當一個頁面請求發生時,SAPI層將控制權交給PHP層。於是PHP設定了用於回覆本次請求所需的環境變數。同時,它還建立一個變量表,用來存放執行過程中產生的變數名和值。
  • PHP呼叫各個模組的RINIT方法,即“請求初始化”。一個經典的例子是Session模組的RINIT,如果在php.ini中啟用了Session模組,那在呼叫該模組的RINIT時就會初始化$_SESSION變數,並將相關內容讀入;
  • RINIT方法可以看作是一個準備過程,在程式執行之間就會自動啟動。

  一個典型的RINIT方法如下:
PHP_RINIT_FUNCTION(extension_name) {
/* Initialize session variables, pre-populate variables, redefine global variables etc */
}
PHP關閉第一步
  如同PHP啟動一樣,PHP的關閉也分兩步:

  • 一旦頁面執行完畢(無論是執行到了檔案末尾還是用exit或die函式中止),PHP就會啟動清理程式。它會按順序呼叫各個模組的RSHUTDOWN方法。
  • RSHUTDOWN用以清除程式執行時產生的符號表,也就是對每個變數呼叫unset函式。

  一個典型的RSHUTDOWN方法如下:
PHP_RSHUTDOWN_FUNCTION(extension_name) {
/* Do memory management, unset all variables used in the last PHP call etc */
}
PHP關閉第二步
  最後,所有的請求都已處理完畢,SAPI也準備關閉了,PHP開始執行第二步:

  • PHP呼叫每個擴充套件的MSHUTDOWN方法,這是各個模組最後一次釋放記憶體的機會。

  一個典型的RSHUTDOWN方法如下:
PHP_MSHUTDOWN_FUNCTION(extension_name) {
/* Free handlers and persistent memory etc */
}
  這樣,整個PHP生命週期就結束了。要注意的是,只有在伺服器沒有請求的情況下才會執行“啟動第一步”和“關閉第二步”。

下面的是用一些圖示來說明的!

PHP底層工作原理

wps_clip_image-29471

圖1 php結構

從圖上可以看出,php從下到上是一個4層體系

①Zend引擎

Zend整體用純c實現,是php的核心部分,它將php程式碼翻譯(詞法、語法解析等一系列編譯過程)為可執行opcode的處理並實現相應的處理方法、實現了基本的資料結構(如hashtable、oo)、記憶體分配及管理、提供了相應的api方法供外部呼叫,是一切的核心,所有的外圍功能均圍繞zend實現。

②Extensions

圍繞著zend引擎,extensions通過元件式的方式提供各種基礎服務,我們常見的各種內建函式(如array系列)、標準庫等都是通過extension來實現,使用者也可以根據需要實現自己的extension以達到功能擴充套件、效能優化等目的(如貼吧正在使用的php中間層、富文字解析就是extension的典型應用)。

③Sapi

Sapi全稱是Server Application Programming Interface,也就是服務端應用程式設計介面,sapi通過一系列鉤子函式,使得php可以和外圍互動資料,這是php非常優雅和成功的一個設計,通過sapi成功的將php本身和上層應用解耦隔離,php可以不再考慮如何針對不同應用進行相容,而應用本身也可以針對自己的特點實現不同的處理方式。後面將在sapi章節中介紹

④上層應用

這就是我們平時編寫的php程式,通過不同的sapi方式得到各種各樣的應用模式,如通過webserver實現web應用、在命令列下以指令碼方式執行等等。

構架思想:

引擎(Zend)+元件(ext)的模式降低內部耦合

中間層(sapi)隔絕web server和php

**************************************************************************

如果php是一輛車,那麼

車的框架就是php本身

Zend是車的引擎(發動機)

Ext下面的各種元件就是車的輪子

Sapi可以看做是公路,車可以跑在不同型別的公路上

而一次php程式的執行就是汽車跑在公路上。

因此,我們需要:效能優異的引擎+合適的車輪+正確的跑道

Apache和php的關係

Apache對於php的解析,就是通過眾多Module中的php Module來完成的。

wps_clip_image-31721

把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的生命週期

Apach的請求處理流程

Apache請求處理迴圈詳解 
    Apache請求處理迴圈的11個階段都做了哪些事情呢?(這11個階段難道就是nginx中對應的11個處理階段???

1、Post-Read-Request階段

    在正常請求處理流程中,這是模組可以插入鉤子的第一個階段。對於那些想很早進入處理請求的模組來說,這個階段可以被利用。

    2、URI Translation階段 
    Apache在本階段的主要工作:將請求的URL對映到本地檔案系統。模組可以在這階段插入鉤子,執行自己的對映邏輯。mod_alias就是利用這個階段工作的。

    3、Header Parsing階段 
    Apache在本階段的主要工作:檢查請求的頭部。由於模組可以在請求處理流程的任何一個點上執行檢查請求頭部的任務,因此這個鉤子很少被使用。mod_setenvif就是利用這個階段工作的。

    4、Access Control階段 
    Apache在本階段的主要工作:根據配置檔案檢查是否允許訪問請求的資源。Apache的標準邏輯實現了允許和拒絕指令。mod_authz_host就是利用這個階段工作的。

    5、Authentication階段 
     Apache在本階段的主要工作:按照配置檔案設定的策略對使用者進行認證,並設定使用者名稱區域。模組可以在這階段插入鉤子,實現一個認證方法。

    6、Authorization階段 
    Apache在本階段的主要工作:根據配置檔案檢查是否允許認證過的使用者執行請求的操作。模組可以在這階段插入鉤子,實現一個使用者許可權管理的方法。

    7、MIME Type Checking階段 
    Apache在本階段的主要工作:根據請求資源的MIME型別的相關規則,判定將要使用的內容處理函式。標準模組mod_negotiation和mod_mime實現了這個鉤子。

    8、FixUp階段 
    這是一個通用的階段,允許模組在內容生成器之前,執行任何必要的處理流程。和Post_Read_Request類似,這是一個能夠捕獲任何資訊的鉤子,也是最常使用的鉤子。

    9、Response階段 
    Apache在本階段的主要工作:生成返回客戶端的內容,負責給客戶端傳送一個恰當的回覆。這個階段是整個處理流程的核心部分。

    10、Logging階段 
    Apache在本階段的主要工作:在回覆已經發送給客戶端之後記錄事務。模組可能修改或者替換Apache的標準日誌記錄。

11、CleanUp階段 
    Apache在本階段的主要工作:清理本次請求事務處理完成之後遺留的環境,比如檔案、目錄的處理或者Socket的關閉等等,這是Apache一次請求處理的最後一個階段。

LAMP架構

從下往上四層:

①liunx 屬於作業系統的底層

②apache伺服器,屬於次伺服器,溝通linux和PHP

③php:屬於服務端程式語言,通過php_module 模組 和apache關聯

④mysql和其他web服務:屬於應用服務,通過PHP的Extensions外 掛模組和mysql關聯

更深入的學習和了解可以檢視下面: