探究PHP底層

1、PHP是什么?

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

1、 解釋器部分(Zend 以引擎),負責對輸入代碼的分析、翻譯和執行;
2、 功能性部分(PHP功能函數以及擴展),負責具體實現語言的各種功能(比如它的函數等等);
3、 接口部分(SAPI),負責同 WEB 服務器的會話等功能。

Zend包括了第一部分的全部和第二部分的局部,PHP內核 包括了第二部分的局部和第三部分的全部。他們合起來稱之為 PHP 包。Zend 構成了語言的核心,同時也包含了一些最基本的 PHP 預定義函數的實現。PHP 包(內核)則包含了所有創造出語言本身各種顯著特性的模塊。

                  1.png

                                       

                                                                                                     (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應用、在命令行下以腳本方式運行等等。

          2.jpg

                                                                              (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 :這是webserverphp直接的另一種交互方式,也就是大名鼎鼎的fastcgi協議,在最近今年fastcgi+php得到越來越多的應用,也是異步webserver所唯一支持的方式。

3)、cli :命令行調用的應用模式

如圖:Sapi的簡單示意圖:

                                       3.jpg

 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路徑  
   
    ...  
    ...  
};

這里介紹一下其中一些主要函數

· startupphp被調用時初始化操作,比如cgi模式,在startup的時候會加載所有的extension并執行模塊初始化工作。

· shutdownphp關閉時收尾工作

· activate:請求初始化

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

· ub_write:指定數據輸出方式,比如apache2handler方式,由于php作為apache的一個so存在,因此其輸出也就是調                          用apacheap_write函數,而在cgi模式下,會系統調用write。

·  sapi_error:錯誤處理函數

·  read_post:讀取post數據

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

在php源碼中,sapi實現了很多接口:如下圖:

4.jpg

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代碼的執行過程如下圖:

                           5.jpg


        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程序執行的最基本單位。

轉自:http://blog.csdn.net/hguisu/article/details/7394430

原創文章,作者:s19930811,如若轉載,請注明出處:http://www.www58058.com/3045

(1)
s19930811s19930811
上一篇 2015-04-10
下一篇 2015-04-12

相關推薦

  • 壓縮與歸檔

    一、壓縮     壓縮:根據一定算法將數據以更加節省空間的形式存放。下面來看一下Linux常見的壓縮工具:     1、gzip/gunzip         后綴名:.gz   …

    Linux干貨 2015-05-04
  • 細數Linux發行版

    什么是Linux 廣義上講:Linux內核+應用程序狹義上講:Linux內核  > Linux內核指的是我們通常所說的Kernel,主要用于負責系統調用、進程管理、內存管理、文件系統管理等功能。  應用程序指的是由GNU組織提供的開源的、通用的應用程序,如gcc、glibc、vi等。 我們平常所說的Linux,通常指廣義層面上的Li…

    Linux干貨 2017-08-30
  • 馬哥教育網絡班22期+第6周課程練習

    請詳細總結vim編輯器的使用并完成以下練習題 1、vi的基本概念 基本上vi可以分為三種狀態,分別是命令模式(command mode)、插入模式(Insert mode)和底行模式(last line mode),各模式的功能區分如下: 1) 命令行模式command mode) 控制屏幕光標的移…

    Linux干貨 2016-09-26
  • Shell腳本編程初步

        shell是指一種應用程序,這個應用程序提供了一個界面,用戶通過這個界面訪問操作系統內核的服務。shell腳本(shell script),是一種為shell編寫的腳本程序。業界所說的shell通常都是指shell腳本,但shell和shell script是兩個不同的概念。shell編程跟java、php編程…

    Linux干貨 2016-08-24
  • Linux 第九天: 練習和作業

    Linux 第九天: 練習和作業       編寫腳本/root/bin/systeminfo.sh 顯示當前主機系統信息 包括主機名 ipv4地址 操作系統版本 內核版本 CPU信號 內存大小 硬盤大小 server_ip=`ifconfig|grep'inet\b'|grep -v '…

    Linux干貨 2016-08-15
  • Keepalived實現nginx雙主

    一、架構描述與應用 1. 應用場景 大多數的互聯網公司都會利用nginx的7層反向代理功能來實現后端web server的負載均衡和動靜分離。這樣做的好處是當單臺后端server出現性能瓶頸時可以對其進行橫向擴展從而提高整個系統的并發,同時也可以通過后端server提供的http或tcp監控接口對其進行健康檢查實現自動Failover和Failback。&n…

    Linux干貨 2016-07-16
欧美性久久久久