搜尋
首頁後端開發php教程PHP是怎麼運作的

這篇文章,研究一下PHP程式碼是如何解釋和執行以及PHP腳本運行的生命週期。

概述

PHP服務的啟動。嚴格來說,PHP的相關進程是不需要手動啟動的,它是隨著Apache的啟動而運作的。當然,如果有需要重啟PHP服務的情況下也是可以手動重啟PHP服務的。比如說在有開啟opcode的正式環境更新了程式碼之後,就需要重新啟動PHP才能重新編譯PHP程式碼。

從宏觀來看,PHP內核的實現就是接收輸入的數據,內部做相應的處理然後輸出結果。對PHP核心來說,我們寫的PHP程式碼就是核心接收的輸入數據,PHP核心接收程式碼資料後,對我們寫的程式碼進行程式碼解析和運算執行,最後回傳對應的運算結果。

然而,不同於平常的C語言程式碼,要執行PHP程式碼,首先需要將PHP程式碼「翻譯」成機器語言來執行對應的功能。而要執行「翻譯」這個步驟,就需要PHP核心進行:詞法分析、文法分析等步驟。最後交給PHP內核的Zend Engine進行順次的執行。

詞法分析

將PHP代碼分隔成一個個的「單元」(TOKEN)

語法分析
將「單元」轉換為Zend Engine可執行的操作

Zend Engine
對語法分析得到的操作順次的執行

一切PHP程式(CGI/CLI)的開始都是從SAPI(Server Application Programming Interface)介面開始。 SAPI指的是PHP具體應用的程式介面。例如Apache的mod_php。

PHP開始執行以後會經過兩個主要的階段:處理請求之前的開始階段和請求之後的結束階段。

開始階段

PHP的整個開始階段會經歷模組初始化和模組激活兩個階段。

MINIT

即模組初始化階段,發生在Apache/Nginx啟動以後的整個生命週期或命令列程式整個執行過程中,此階段只進行一次

RINIT
模組激活,發生在請求階段。做一些初始化工作:如註冊常數、定義模組使用的類別等等

模組在實作時可以透過如下巨集來實現這些回呼函數:

PHP_MINIT_FUNCTION(myphpextension)
{
//注册常量或者类等初始化操作
return SUCCESS;
}

PHP_RINIT_FUNCTION(myphpextension)
{
//例如记录请求开始时间
//随后在请求结束的时候记录结束时间。这样我们就能够记录处理请求所花费时间了
return SUCCESS;
}

PHP腳本請求處理完就進入了結束階段,一般腳本執行到結尾或呼叫exit或die函數,PHP就進入結束階段。

結束階段

PHP的結束階段分為停用模組和關閉模組兩個環節。

RSHUTDOWN
停用模組(對應RINIT)

MSHUTDOWN
關閉模組(對應MINIT)

CLI/CGI模式的PHP屬於單一進程的SAPI模式。意思是說,PHP腳本在執行一次之後就關閉掉,所有的變數和函數都不能繼續使用。即在CGI模式下,同一個php檔案的變數在其他php檔案中不能使用。

下面用一個例子來看看單執行緒PHP的SAPI生命週期。

單執行緒SAPI生命週期
如:

php -f test.php

呼叫各個擴充的MINIT 模組初始化
  請求test.php
  》 test.    呼叫各個擴充的RSHUTDOWN 停用模組
執行完t​​est.php後清理變數和記憶體
呼叫各個擴充的MSHUTDOWN 關閉模組
停止PHP執行

以上是一個簡單的執行流程,下面做一些補充。

PHP在呼叫每個模組的模組初始化前,會有一個初始化的過程,包括:

初始化若干全域變數

大多數情況下是將其設為NULL。

初始化若干常數

這裡的常數是PHP本身的一些常數。


初始化Zend引擎和核心元件

這裡的初始化操作包括記憶體管理初始化、全域使用的函數指標初始化,對PHP原始檔進行詞法分析、語法分析、中間程式碼執行的函數指標的賦值,初始化若干HashTable(例如函數表,常量表等等),為ini文件解析做準備,為PHP源文件解析做準備,註冊內置函數、標準常數、GLOBALS全局變量等


解析php.ini

讀取php.ini文件,設置配置參數,載入zend擴充並註冊PHP擴充函數。


全域操作函數的初始化

初始化在用戶空間所使用頻率很高的一些全域變量,如:$_GET、$_POST、$_FILES 等。


初始化靜態建置的模組和共用模組(MINIT)

初始化預設載入的模組。

模組初始化執行操作:
將模組註冊到已註冊模組列表
將每個模組中包含的函數註冊到函數表

禁用函數和類別

會呼叫zend_disable_function函數將PHP的配置文件中的disable_functionsable_functions變數代表的函數從CG(function_table)函數表中刪除。

啟動Zend引擎

使用init_compiler函數來初始化編譯器。

啟動SAPI
使用sapi_activate函數來初始化SG(sapi_headers)和SG(request_info),並且針對HTTP請求的方法設定一些內容。

環境初始化
初始化在使用者控制項需要用到的一些環境變數。包括伺服器環境、請求資料環境等。

模組請求初始化
PHP呼叫zend_activate_modules函數遍歷註冊在module_registry變數中的所有模組,呼叫其RINIT方法方法實現模組的請求初始化操作。

在處理了文件相關的內容後,PHP會呼叫​​php_request_startup做請求初始化操作:

啟動Zend引擎
啟動SAPI
環境初始化
模組請求初始化


就開始執行PHP程式。 PHP透過zend_compile_file做詞法分析、語法分析和中間程式碼產生操作,傳回此檔案的所有中間程式碼。如果解析的檔案有產生有效的中間程式碼,則呼叫zend_excute執行中間程式碼。 。如果在執行過程中出現異常且使用者有定義對這些異常的處理,則呼叫這些異常處理函數。在所有的操作都處理完後,PHP透過EG(return_value_ptr_ptr)傳回結果。


DEACTIVATION(關閉請求)

PHP關閉請求的過程是一個若干個關閉操作的集合,這個集合存在於php_request_shutdown函數中。這個包含:


呼叫所有透過register_shutdown_function()註冊的函數。這些在關閉時呼叫的函數是在用戶空間添加進來的。
執行所有可用的__destruct函數。這裡的析構函數包括在物件池(EG(objects_store)中的所有物件的析構函數以及EG(symbol_table)中各個元素的析構方法。
將所有的輸出刷出去。
發送HTTP應答頭。
銷毀全域變數表(PG(http_globals))的變數。
透過zend_deactivate函數,關閉詞法分析器、語法分析器和中間程式碼執行器。函數指標都是NULL。


結束
PHP結束一個進程是,會呼叫sapi_flush函數將最後的內容刷新出去。 (http://www.php-internals.com/book/)

以上就介紹了PHP是怎麼運作的,包括了方面的內容,希望對PHP教學有興趣的朋友有幫助。


陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
php怎么把负数转为正整数php怎么把负数转为正整数Apr 19, 2022 pm 08:59 PM

php把负数转为正整数的方法:1、使用abs()函数将负数转为正数,使用intval()函数对正数取整,转为正整数,语法“intval(abs($number))”;2、利用“~”位运算符将负数取反加一,语法“~$number + 1”。

php怎么实现几秒后执行一个函数php怎么实现几秒后执行一个函数Apr 24, 2022 pm 01:12 PM

实现方法:1、使用“sleep(延迟秒数)”语句,可延迟执行函数若干秒;2、使用“time_nanosleep(延迟秒数,延迟纳秒数)”语句,可延迟执行函数若干秒和纳秒;3、使用“time_sleep_until(time()+7)”语句。

php怎么除以100保留两位小数php怎么除以100保留两位小数Apr 22, 2022 pm 06:23 PM

php除以100保留两位小数的方法:1、利用“/”运算符进行除法运算,语法“数值 / 100”;2、使用“number_format(除法结果, 2)”或“sprintf("%.2f",除法结果)”语句进行四舍五入的处理值,并保留两位小数。

php怎么根据年月日判断是一年的第几天php怎么根据年月日判断是一年的第几天Apr 22, 2022 pm 05:02 PM

判断方法:1、使用“strtotime("年-月-日")”语句将给定的年月日转换为时间戳格式;2、用“date("z",时间戳)+1”语句计算指定时间戳是一年的第几天。date()返回的天数是从0开始计算的,因此真实天数需要在此基础上加1。

php怎么判断有没有小数点php怎么判断有没有小数点Apr 20, 2022 pm 08:12 PM

php判断有没有小数点的方法:1、使用“strpos(数字字符串,'.')”语法,如果返回小数点在字符串中第一次出现的位置,则有小数点;2、使用“strrpos(数字字符串,'.')”语句,如果返回小数点在字符串中最后一次出现的位置,则有。

php字符串有没有下标php字符串有没有下标Apr 24, 2022 am 11:49 AM

php字符串有下标。在PHP中,下标不仅可以应用于数组和对象,还可应用于字符串,利用字符串的下标和中括号“[]”可以访问指定索引位置的字符,并对该字符进行读写,语法“字符串名[下标值]”;字符串的下标值(索引值)只能是整数类型,起始值为0。

php怎么替换nbsp空格符php怎么替换nbsp空格符Apr 24, 2022 pm 02:55 PM

方法:1、用“str_replace(" ","其他字符",$str)”语句,可将nbsp符替换为其他字符;2、用“preg_replace("/(\s|\&nbsp\;||\xc2\xa0)/","其他字符",$str)”语句。

php怎么读取字符串后几个字符php怎么读取字符串后几个字符Apr 22, 2022 pm 08:31 PM

在php中,可以使用substr()函数来读取字符串后几个字符,只需要将该函数的第二个参数设置为负值,第三个参数省略即可;语法为“substr(字符串,-n)”,表示读取从字符串结尾处向前数第n个字符开始,直到字符串结尾的全部字符。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
1 個月前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Atom編輯器mac版下載

Atom編輯器mac版下載

最受歡迎的的開源編輯器

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具