日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

王帅:深入PHP内核(二)——SAPI探究(精辟)

發布時間:2024/9/20 php 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 王帅:深入PHP内核(二)——SAPI探究(精辟) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

SAPI是Server Application Programming Interface(服務器應用編程接口)的縮寫。PHP通過SAPI提供了一組接口,供應用和PHP內核之間進行數據交互。

簡單的講,就像函數的輸入和輸出一樣,我們通過Linux命令行執行一段PHP代碼,本質是Linux的Shell通過PHP的SAPI傳入一組參數,Zend引擎執行后,返回給shell,由shell顯示出來的過程。同樣的,通過Apache調用PHP,通過Web服務器給SAPI傳入數據,Zend引擎執行后,返回給Apache,由Apache顯示在頁面上。


圖1. PHP架構圖

PHP提供很多種形式的接口,包括apache、apache2filter、apache2handler、caudium、cgi 、cgi-fcgi、cli、cli-server、continuity、embed、isapi、litespeed、milter、nsapi、phttpd pi3web、roxen、thttpd、tux和webjames。但是常用的只有5種形式,CLI/CGI(命令行)、Multiprocess(多進程)、Multithreaded(多線程)、FastCGI和Embedded(內嵌)。

PHP提供了一個函數查看當前SAPI接口類型:

[php] view plaincopy
  • string?php_sapi_name?(?void?)??
  • PHP的運行和加載

    無論使用哪種SAPI,在PHP執行腳本前后,都包含一系列事件:Module的Init(MINT)和Shutdown(MSHUTDOWN),Request 的Init(RINT)和Shutdown(RSHUTDOWN)。 第一階段是PHP模塊初始化階段(MINT),可以初始化擴展內部變量、分配資源和注冊資源處理器,在整個PHP實例生命周期內,該過程只執行一次。

    什么是PHP模塊?通過上面的PHP架構圖,在PHP中可以使用get_loaded_extensions 函數來查看所有編譯并加載的模塊/擴展,相當于CLI模式下的php -m。

    以PHP的Memcached擴展源代碼為例:

    [php] view plaincopy
  • PHP_MINIT_FUNCTION(memcached)?{???????
  • ????zend_class_entry?ce;??????
  • ????memcpy(&memcached_object_handlers,zend_get_std_object_handlers(),?sizeof(zend_object_handlers));??????
  • memcached_object_handlers.clone_obj?=?NULL;?????/*?執行了一些類似的初始化操作?*/???????
  • return?SUCCESS;???
  • }??
  • 第二階段是請求初始化階段(RINT),在模塊初始化并激活后,會創建PHP運行環境,同時調用所有模塊注冊的RINT函數,調用每個擴展的請求初始化函數 ,設定特定的環境變量、分配資源或執行其他任務,如審核。 [php] view plaincopy
  • PHP_RINIT_FUNCTION(memcached)?{???????
  • ????/*?執行一些關于請求的初始化?*/????????
  • ????return?SUCCESS;???
  • }??
  • 第三階段,請求處理完成后,會調用PHP_RSHUTDOWN_FUNCTION進行回收,這是每個擴展的請求關閉函數,執行最后的清理工作。Zend引擎執行清理過程、垃圾收集、對之前的請求期間用到的每個變量執行unset。請求完成可能是執行到腳本完成,也可能是調用die()或exit()函數完成

    第四階段,當PHP生命周期結束時候,PHP_MSHUTDOWN_FUNCTION對模塊進行回收處理,這是每個擴展的模塊關閉函數,用于關閉自己的內核子系統。

    [php] view plaincopy
  • PHP_MSHUTDOWN_FUNCTION(memcached)?{?/*?執行關于模塊的銷毀工作?*/?UNREGISTER_INI_ENTRIES();?return?SUCCESS;?}??
  • 常見的運行模式

    常見的SAPI模式有五種:

    • CLI和CGI模式(單進程模式)
    • 多進程模式
    • 多線程模式
    • FastCGI模式
    • 嵌入式

    1. CLI/CGI模式

    CLI和CGI都屬于單進程模式,PHP的生命周期在一次請求中完成。也就是說每次執行PHP腳本,都會執行第二部分講的四個INT和Shutdown事件。

    圖2. CGI/CLI生命周期

    2. 多進程模式(Multiprocess)

    多進程模式可以將PHP內置到Web Server中,PHP可以編譯成Apache下的prefork MPM模式和APXS模塊,當Apache啟動后,會fork很多子進程,每個子進程擁有自己獨立的進程地址空間。


    圖3. 多進程模式生命周期

    在一個子進程中,PHP的生命周期是調用MINT啟動后,執行多次請求(RINT/RSHUTDOWN),在Apache關閉或進程結束后,才會調用MSHUTDOWN進行回收階段。


    圖4. 多進程的生命周期

    多進程模型中,每個子進程都是獨立運行,沒有代碼和數據共享,因此一個子進程終止退出和重新生成,不會影響其他子進程的穩定。

    3. 多線程模式(Multithreaded)

    Apache2的Worker MPM采用了多線程模型,在一個進程下創建多個線程,在同一個進程地址空間執行。


    圖5. 多線程生命周期

    4. FastCGI模式

    在我們用的Nginx+PHP-FPM用的就是FastCGI模式,Fastcgi是一種特殊的CGI模式,是一種常駐進程類型的CGI,運行后可以Fork多個進程,不用花費時間動態的Fork子進程,也不需要每次請求都調用MINT/MSHUTDOWN。PHP通過PHP-FPM來管理和調度FastCGI的進程池。Nginx和PHP-FPM通過本地的TCP Socket和Unix Socket 進行通信。


    圖6. FastCGI模式生命周期

    PHP-FPM進程管理器自身初始化,啟動多個CGI解釋器進程等待來自Nginx的請求。當客戶端請求達到PHP-FPM,管理器選擇到一個CGI進程進行處理,Nginx將CGI環境變量和標準輸入發送到一個PHP-CIG子進程。PHP-CGI子進程處理完成后,將標準輸出和錯誤信息返回給Nginx,當PHP-CGI子進程關閉連接時,請求處理完成。PHP-CGI子進程等待著下一個連接。

    可以想象CGI的系統開銷有多大。每一個Web 請求PHP都必須重新解析php.ini、載入全部擴展并始化全部數據結構。使用FastCGI,所有這些都只在進程啟動時發生一次。另外,對于數據庫和Memcache的持續連接可以工作。

    5. 內嵌模式(Embedded)

    Embed SAPI是一種特殊的SAPI,允許在C/C++語言中調用PHP提供的函數。這種SAPI和CLI模式一樣,按照Module Init => Request Init => Request => Request Shutdown => Module Shutdown的模式運行。

    Embed SAPI可以調用PHP豐富的類庫,也可以實現高級玩法,比如可以查看PHP的OPCODE(PHP執行的中間碼,Zend引擎的指令,由PHP代碼生成)。

    詳細請見: http://www.laruence.com/2008/09/23/539.html

    SAPI的運行機制

    我們以CGI為例,看一下SAPI的運行機制。

    [php] view plaincopy
  • static?sapi_module_struct?cgi_sapi_module?=?{???????
  • ????"cgi-fcgi",?????????????????????/*?輸出給php_info()使用?*/?????"CGI/FastCGI",??????????????????/*?pretty?name?*/????????
  • ????php_cgi_startup,????????????????/*?startup?當SAPI初始化時,首先會調用該函數?*/???????
  • ????php_module_shutdown_wrapper,????/*?shutdown??關閉函數包裝器,它用來釋放所有的SAPI的數據結構、內存等,調用php_module_shutdown?*/????????
  • ????sapi_cgi_activate,??????????????/*?activate??此函數會在每個請求開始時調用,它會做初始化,資源分配?*/???????
  • ????sapi_cgi_deactivate,????????????/*?deactivate??此函數會在每個請求結束時調用,它用來確保所有的數據都得到釋放?*/????????
  • ????sapi_cgi_ub_write,??????????????/*?unbuffered?write??不緩存的寫操作(unbuffered?write),它是用來向SAPI外部輸出數據?*/???????
  • ????sapi_cgi_flush,?????????????????/*?flush??刷新輸出,在CLI模式下通過使用C語言的庫函數fflush實現*/?????NULL,???????????????????????????/*?get?uid?*/???????
  • ????sapi_cgi_getenv,????????????????/*?getenv?根據name查找環境變量?*/????????
  • ????php_error,??????????????????????/*?error?handler?注冊錯誤處理函數??*/????????
  • ????NULL,???????????????????????????/*?header?handler?PHP調用header()時候被調用?*/???????
  • ????sapi_cgi_send_headers,??????????/*?send?headers?handler?發送頭部信息*/???????
  • ????NULL,???????????????????????????/*?send?header?handler?發送一個單獨的頭部信息?*/????????
  • ????sapi_cgi_read_post,?????????????/*?read?POST?data??當請求的方法是POST時,程序獲取POST數據,寫入$_POST數組?*/???????
  • ????sapi_cgi_read_cookies,??????????/*?read?Cookies?獲取Cookie值??*/????????
  • ????sapi_cgi_register_variables,????/*?register?server?variables?給$_SERVER添加環境變量?*/???????
  • ????sapi_cgi_log_message,???????????/*?Log?message?輸出錯誤信息?*/???????
  • ????NULL,???????????????????????????/*?Get?request?time?*/???????
  • ????NULL,???????????????????????????/*?Child?terminate?*/????????
  • ????STANDARD_SAPI_MODULE_PROPERTIES???
  • };???
  • 由上面代碼可見,PHP的SAPI像是面向對象中基類,SAPI.h和SAPI.c包含的函數是抽象基類的聲明和定義,各個服務器用的SAPI模式,則是繼承了這個基類,并重新定義基類方法的子類。

    總結

    PHP的SAPI是Zend引擎提供的一組標準交互接口,通過注冊初始化、析構、輸入、輸出等接口,我們可以將應用程序運行在Zend引擎上,也可以把PHP嵌入到類似Apache的Web Server中。PHP常見的SAPI模式有五種,CGI/CLI模式、多進程模式、多線程模式、FastCGI模式和內嵌模式。

    了解PHP的SAPI機制意義重大,幫助我們理解PHP的生命周期,并了解如何更好的通過C/C++為PHP編寫擴展,并在生命周期中找到提高系統性能的方式。

    關于作者:王帥,騰訊企業QQ SaaS團隊Leader。

    來源:http://www.csdn.net/article/2014-09-26/2821885-exploring-of-the-php-2

    總結

    以上是生活随笔為你收集整理的王帅:深入PHP内核(二)——SAPI探究(精辟)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。