PHP擴展-生命周期和記憶體管理

来源:http://www.cnblogs.com/beatzeus/archive/2016/11/16/6071902.html
-Advertisement-
Play Games

1. PHP源碼結構 PHP的內核子系統有兩個,ZE(Zend Engine)和PHP Core.ZE負責將PHP腳本解析成機器碼(也成為token符)後,在進程空間執行這些機器碼;ZE還負責記憶體管理,變數作用域管理和對PHP函數的調度管理。 PHP Core負責和SAPI層的通信;PHP Core ...


1. PHP源碼結構

PHP的內核子系統有兩個,ZE(Zend Engine)和PHP Core.
ZE負責將PHP腳本解析成機器碼(也成為token符)後,在進程空間執行這些機器碼;ZE還負責記憶體管理,變數作用域管理和對PHP函數的調度管理。

PHP Core負責和SAPI層的通信;PHP Core也為safe_mode, open_basedir的檢查提供了統一控制層;PHP Core還提供了streams層,用於用戶域的文件和網路IO操作。其中SAPI(Server Application Programming Interface)通常包含Nginx,Apache,IIS,CLI,CGI等主機環境。

PHP擴展在ZE和PHP Core的基礎上提供對各種常用操作的封裝,比如對mysql,redis,memcache,sqlite等的讀寫,對json,xml文件的解析,對soap,sokcet,curl的網路協議的封裝,對加密解密壓縮解壓縮等的封裝,對圖像處理的封裝等等。有些擴展是從零開始實現某個功能,比如按照redis的通信協議使用C來實現和redis的通信;有些擴展則是通過調用系統已有的庫,比如圖片處理的gb擴展需要系統本身要安裝了相應的gd庫。
在PHP源碼php-5.6.24/ext中提供了78個擴展。

總之,由ZE和PHP Core提供基礎的架構,由EXT(擴展)提供用戶域的各種操作。
以php-5.6.24源碼為例,ZE對應文件夾php-5.6.24/Zend, PHP Core對應文件夾php-5.6.24/main, 擴展對應文件夾php-5.6.24/ext。

2. PHP擴展的生命周期

PHP在接收到SAPI命令時,首先初始化並啟動它的內核子系統,在內核子系統的啟動快結束時,PHP開始載入它的擴展代碼並對擴展初始化,此時PHP將調用每個模塊的初始化常式Module Initialization routine (MINIT)。

MINIT(Module Initialization)
PHP調用MINIT相關常式,使得每個擴展有機會初始化內部變數、分配資源、註冊資源處理句柄,以及向ZE註冊自己的函數,以便於腳本調用這其中的函數時候ZE知道執行哪些代碼

RINIT(Request Initialization)
在模塊初始化完成後,PHP等待來自SAPI的請求,當接收到SAPI請求後,由ZE為當前被請求的php腳本創建運行環境,並調用每個擴展的Request Initialization(RINIT)函數,使得每個擴展有機會設定特定的環境變數,根據請求分配資源,或者執行其他任務,如審核。

這裡所說的SAPI請求分為兩類,一類是Apache, IIS, 和其他成熟的web server SAPIs,他們在啟動時PHP先執行了MINIT,之後等待來自用戶的頁面請求,當收到請求後執行RINIT;另一類SAPI請求則是CGI or CLI SAPIs,PHP在收到這類SAPI請求時,執行完MINIT馬上就執行RINIT。

當RINIT請求初始化完畢後,ZE接回控制權並將當前被請求的腳本翻譯成tokens, 最終構成opcodes(操作碼),opcodes被執行過程中,如果某個opcode要求執行某個擴展函數,這是ZE就會將相關參數綁定到改函數,並將控制權臨時交給該函數去執行,直到該函數執行完畢。

RSHUTDOWN(Request Shutdown)
PHP腳本運行結束後,PHP調用每個擴展的請求關閉(RSHUTDOWN)函數以執行最後的清理工作(如將session變數存入磁碟)。接下來,ZE執行清理過程(垃圾收集),有效地對之前的請求期間用到的每個變數執行unset()。

MSHUTDOWN(Module Shutdown)
當RSHUTDOWN完成後,PHP繼續等待SAPI的其他文檔請求或者是關閉信號。對於CGI和CLI等SAPI,沒有“下一個請求”,所以SAPI立刻開始關閉。關閉期間,PHP再次遍歷每個擴展,調用其模塊關閉(MSHUTDOWN)函數,並最終關閉自己的內核子系統。

GINIT
初始化全局變數

GSHUTDOWN
釋放全局變數

MINFO
設置phpinfo模塊的信息,phpinfo要等級每個擴展的配置信息

// main/php.h
 #define PHP_MINIT       ZEND_MODULE_STARTUP_N
 #define PHP_MSHUTDOWN   ZEND_MODULE_SHUTDOWN_N
 #define PHP_RINIT       ZEND_MODULE_ACTIVATE_N
 #define PHP_RSHUTDOWN   ZEND_MODULE_DEACTIVATE_N
 #define PHP_MINFO       ZEND_MODULE_INFO_N
 #define PHP_GINIT       ZEND_GINIT
 #define PHP_GSHUTDOWN   ZEND_GSHUTDOWN

 #define PHP_MINIT_FUNCTION      ZEND_MODULE_STARTUP_D
 #define PHP_MSHUTDOWN_FUNCTION  ZEND_MODULE_SHUTDOWN_D
 #define PHP_RINIT_FUNCTION      ZEND_MODULE_ACTIVATE_D
 #define PHP_RSHUTDOWN_FUNCTION  ZEND_MODULE_DEACTIVATE_D
 #define PHP_MINFO_FUNCTION      ZEND_MODULE_INFO_D
 #define PHP_GINIT_FUNCTION      ZEND_GINIT_FUNCTION
 #define PHP_GSHUTDOWN_FUNCTION  ZEND_GSHUTDOWN_FUNCTION

 

3. PHP擴展的記憶體管理

ZE在執行自己內部的記憶體管理時,通過附加的標誌來標識某某記憶體變數是否是持久性的,對於非持久記憶體,ZE會去清理。但在擴展內部最好還是自己去清理非持久記憶體,因為擴展自己請求分配的非持久記憶體,將在長時間內保持為未回收狀態,這樣與之相關的資源長時間得不到釋放。

 

參考文章:Extension Writing Part I: Introduction to PHP and Zend

qrcode_for_gh_61c6224cfae9_258


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.內置函數補充 callable(object) 檢查對象object是否可調用 1、類是可以被調用的 2、實例是不可以被調用的,除非類中聲明瞭__call__方法 def f1(): print("test") f2 = "test" print(callable(f1)) print(call... ...
  • 關於php的curl一系列函數,這裡解釋一下它們的作用。 在html中,我們可以通過form設置http的post和get提交,但假如我們獲取的數據不是從html中來的,而是php腳本主動向其他伺服器提交呢?這個時候,我們應該怎麼實現post和get提交數據呢?答案就是php的curl函數或者str ...
  • ...
  • 今天開始打算每周都寫點東西來記錄自己的學習,自己mark一下。 字典是python中最靈活的內置數據結構,字典是無序的集合(字典的順序隨機是為了快速執行鍵查找),python採用最優化的散列演算法來尋找鍵;字典類似於java中的map,但是沒有java中map那麼多類型(HashMap,TreeMap ...
  • python的類(class)和實例(instance) 假設一種鞋子(shoe)有尺碼(size)和顏色(color)兩種屬性,以此為例。 類可以起到模板的作用,因此,可以在創建實例的時候,把一些我們認為必須綁定的屬性強制填寫進去。通過定義一個特殊的__init__方法,在創建實例的時候,就把si ...
  • 對於OpenMP,小喵其實並不是瞭解很多,而且小喵本身也只用到了OpenMP的最簡單的功能。在這裡主要是分享一個自己常用的寫簡單的並行程式的思路。希望能幫助到大家。 這個設計模式的主要特點如下: 1,處理的任務是獨立的; 2,可以在運行中輸出結果,而不是最終才輸出; 3,有限的資源占用; 4,在每次... ...
  • 描述 Description 以下的數字倒直角三角形是由二個數確定的:一個數是行數R,1<=R<=39,另一個是種子數S,1<=S<=9。S放在左上角,照著樣例輸出文件的樣子,寫一個程式,根據輸入的二個數列印出相應的數字倒直角三角形。 輸入格式 Input Format 單獨一行,二個用空格隔開的整 ...
  • ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...