1. 程式人生 > 程式設計 >深入解析PHP底層機制及相關原理

深入解析PHP底層機制及相關原理

1、PHP是什麼?

PHP 指的是我們從外面看到的一套完整的系統。這聽起來有點糊塗,但其實並不複雜(PHP4 內部結構圖)。從功能上來分:我們可以分為三部分:

1、 直譯器部分(Zend 以引擎),負責對輸入程式碼的分析、翻譯和執行;

2、 功能性部分(PHP功能函式以及擴充套件),負責具體實現語言的各種功能(比如它的函式等等);

3、 介面部分(SAPI),負責同 WEB 伺服器的會話等功能。 Zend包括了第一部分的全部和第二部分的區域性,PHP核心 包括了第二部分的區域性和第三部分的全部。他們合起來稱之為 PHP 包。Zend 構成了語言的核心,同時也包含了一些最基本的 PHP 預定義函式的實現。PHP 包(核心)則包含了所有創造出語言本身各種顯著特性的模組。

深入解析PHP底層機制及相關原理

(PHP 內部結構圖)

從內容模組上來分:我們可以分為四層體系結構:

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

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

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

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

深入解析PHP底層機制及相關原理

(php結構 )

其架構思想:引擎(Zend)+擴充套件(ext)的模式:降低內部耦合

中間層(sapi):web server和php的通訊介面, 隔絕web server和php。

如果php是一輛車,那麼

車的框架就是php本身,即是我們外面看到一套完整系統。

Zend是車的引擎(發動機)

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

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

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

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

2、php生命週期

檢視:深入理解php底層:php生命週期:http://blog.csdn.net/hguisu/article/details/7377520

3 、sapi

如前所述,sapi通過通過一系列的介面,使得外部應用可以和php交換資料並可以根據不同應用特點實現特定的處理方法,我們常見的一些sapi有:

1) 、apache2handler :這是以apache作為webserver,採用mod_php模式執行時候的處理方式,也是現在應用最廣泛的一種。

2)、cgi :這是webserver和php直接的另一種互動方式,也就是大名鼎鼎的fastcgi協議,在最近今年fastcgi+php得到越來越多的應用,也是非同步webserver所唯一支援的方式。

3)、cli :命令列呼叫的應用模式

如圖:Sapi的簡單示意圖

深入解析PHP底層機制及相關原理

Sapi的定義及主要介面函式:

struct _sapi_module_struct { char *name; // 名字標識 char *pretty_name; // 更好理解的名字 int (*startup)(struct _sapi_module_struct *sapi_module); // 啟動函式 int (*shutdown)(struct _sapi_module_struct *sapi_module); // 關閉方法 int (*activate)(TSRMLS_D); //啟用 int (*deactivate)(TSRMLS_D); // 停用 int (*ub_write)(const char *str,unsigned int str_length TSRMLS_DC); // 沒有快取的寫操作(unbuffered write) void (*flush)(void *server_context); // flush struct stat *(*get_stat)(TSRMLS_D); // get uid char *(*getenv)(char *name,size_t name_len TSRMLS_DC); // getenv void (*sapi_error)(int type,const char *error_msg,...); /* error handler */ int (*header_handler)(sapi_header_struct *sapi_header,sapi_header_op_enum op,sapi_headers_struct *sapi_headers TSRMLS_DC); /* header handler */ /* send headers handler */ int (*send_headers)(sapi_headers_struct *sapi_headers TSRMLS_DC); void (*send_header)(sapi_header_struct *sapi_header,void *server_context TSRMLS_DC); /* send header handler */ int (*read_post)(char *buffer,uint count_bytes TSRMLS_DC); /* read POST data */ char *(*read_cookies)(TSRMLS_D); /* read Cookies */ /* register server variables */ void (*register_server_variables)(zval *track_vars_array TSRMLS_DC); void (*log_message)(char *message); /* Log message */ time_t (*get_request_time)(TSRMLS_D); /* Request Time */ void (*terminate_process)(TSRMLS_D); /* Child Terminate */ char *php_ini_path_override; //覆蓋ini路徑 ... ...};

這裡介紹一下其中一些主要函式

·startup:php被呼叫時初始化操作,比如cgi模式,在startup的時候會載入所有的extension並執行模組初始化工作。

·shutdown:php關閉時收尾工作

·activate:請求初始化

·dectivate:請求結束時收尾工作

·ub_write:指定資料輸出方式,比如apache2handler方式,由於php作為apache的一個so存在,因此其輸出也就是呼叫apache的ap_write函式,而在cgi模式下,會系統呼叫write。

·sapi_error:錯誤處理函式

· read_post:讀取post資料

·register_server_variables:往$_SERVER中註冊環境變數這個一般根據不同協議標準註冊註冊的變數。

在php原始碼中,sapi實現了很多介面:如下圖:

深入解析PHP底層機制及相關原理

4、php指令碼的執行

SAPI處於PHP架構的上層,而真正的指令碼執行是有Zend引擎來完成。

目前語言分為兩類:

第一類:編譯型語言.如c/c++ java之類,他們的共性是執行之前必須對原始碼進行編譯,然後執行編譯後的目標檔案。

第二類語言:解釋型語言:如PHP,Ruby,Python。他們需要直譯器來執行這些原始碼。實際上這些語言還是要經過編譯環節的。只不過他們在執行的時候進行編譯,為了效率,並不是每次執行的時候都會重新編譯,比如PHP的各種opcode快取擴充套件(如APC Xcache等)。

說明:PHP從2000年釋出的PHP4開始就不是解釋性語言。當一個PHP指令碼被執行的時候,首先PHP原始碼由Zend引擎編譯成名為Zend opcodes的機器程式碼。這些程式碼儲存在RAM中。然後執行opcodes執行真正的指令碼。因此,PHP實際上和Java,C#等語言一樣是編譯語言。否則,它的執行會很慢。

我們來看PHP指令碼是怎麼被執行的。如hello.php:

<?php$str = "Hello world!\n";echo $str;

命令列執行:php hello.php

輸出結果顯然是:Hello world!

但是執行指令碼的時候,PHP/Zend做了什麼呢?

4.1、程式的執行:

1)傳遞給php程式需要的執行檔案hello.php,php程式完成基本的準備工作後啟動PHP及Zend引擎,載入註冊的擴充套件模組。

2) 初始化完後讀取指令碼檔案,Zend引擎對指令碼進行此詞法分析,語法分析,然後有Zend引擎編譯成opcode碼,最後執行 opcode碼。

php程式碼的執行過程如下圖:

深入解析PHP底層機制及相關原理

php實現了一個典型的動態語言執行過程:拿到一段程式碼後,經過詞法解析、語法解析等階段後,源程式會被翻譯成一個個指令(opcodes),然後ZEND虛擬機器順次執行這些指令完成操作。PHP本身是用c實現的,因此最終呼叫的也都是c的函式,實際上,我們可以把php看做是一個c開發的軟體。

通過上面描述不難看出,php的執行的核心是翻譯出來的一條一條指令,也即opcode.

4.2、詞法分析和語法分析

直譯器一般包括兩部分:

1)、 讀取源程式,並處理語言結構

2)、處於語言結構並生成目標程式

而Lex和Yacc可以解決第一個問題。很多程式設計都有Lex/Yacc作為語言的詞法語法分析生成器,比如PHP,Python、Ruby已經MySql的sql語言。

Lex生成詞法分析器。

Yacc語法分析生成器

4. 3、opcode

PHP 構建在Zend虛擬機器(Zend VM)之上的,PHP的opcode就是ZEND 虛擬機器中的指令,即Opcode是php程式執行的最基本單位。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。