国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

PHP內(nèi)核探索 —— 如何執(zhí)行PHP腳本:Zend引擎是如何解釋PHP腳本的

瀏覽:3日期:2022-09-16 13:06:00

前面介紹了PHP的生命周期,PHP的SAPI,SAPI處于PHP整個(gè)架構(gòu)較上層,而真正腳本的執(zhí)行主要由Zend引擎來(lái)完成, 這一小節(jié)我們介紹PHP腳本的執(zhí)行。

目前編程語(yǔ)言可以分為兩大類:

第一類是像C/C++, .NET, Java之類的編譯型語(yǔ)言, 它們的共性是:運(yùn)行之前必須對(duì)源代碼進(jìn)行編譯,然后運(yùn)行編譯后的目標(biāo)文件。第二類比如PHP, Javascript, Ruby, Python這些解釋型語(yǔ)言, 他們都無(wú)需經(jīng)過(guò)編譯即可“運(yùn)行”。

雖然可以理解為直接運(yùn)行,但它們并不是真的直接就被能被機(jī)器理解, 機(jī)器只能理解機(jī)器語(yǔ)言,那這些語(yǔ)言是怎么被執(zhí)行的呢, 一般這些語(yǔ)言都需要一個(gè)解釋器, 由解釋器來(lái)執(zhí)行這些源碼, 實(shí)際上這些語(yǔ)言還是會(huì)經(jīng)過(guò)編譯環(huán)節(jié),只不過(guò)它們一般會(huì)在運(yùn)行的時(shí)候?qū)崟r(shí)進(jìn)行編譯。為了效率,并不是所有語(yǔ)言在每次執(zhí)行的時(shí)候都會(huì)重新編譯一遍, 比如PHP的各種opcode緩存擴(kuò)展(如APC, xcache, eAccelerator等),比如Python會(huì)將編譯的中間文件保存成pyc/pyo文件, 避免每次運(yùn)行重新進(jìn)行編譯所帶來(lái)的性能損失。

PHP的腳本的執(zhí)行也需要一個(gè)解釋器, 比如命令行下的php程序,或者apache的mod_php模塊等等。 前面提到了PHP的SAPI接口, 下面就以PHP命令行程序?yàn)槔忉孭HP腳本是怎么被執(zhí)行的。 例如如下的這段PHP腳本:

<?php$str = 'Hello, world!n';echo $str;?>

假設(shè)上面的代碼保存在名為hello.php的文件中, 用PHP命令行程序執(zhí)行這個(gè)腳本:

$ php ./hello.php

這段代碼的輸出顯然是Hello, world!, 那么在執(zhí)行腳本的時(shí)候PHP/Zend都做了些什么呢? 這些語(yǔ)句是怎么樣讓php輸出這段話的呢? 下面將一步一步的進(jìn)行介紹。

程序的執(zhí)行如上例中, 傳遞給php程序需要執(zhí)行的文件, php程序完成基本的準(zhǔn)備工作后啟動(dòng)PHP及Zend引擎, 加載注冊(cè)的擴(kuò)展模塊。初始化完成后讀取腳本文件,Zend引擎對(duì)腳本文件進(jìn)行詞法分析,語(yǔ)法分析。然后編譯成opcode執(zhí)行。 如果安裝了apc之類的opcode緩存, 編譯環(huán)節(jié)可能會(huì)被跳過(guò)而直接從緩存中讀取opcode執(zhí)行。

PHP在讀取到腳本文件后首先對(duì)代碼進(jìn)行詞法分析,PHP的詞法分析器是通過(guò)lex生成的, 詞法規(guī)則文件在$PHP_SRC/Zend/zend_language_scanner.l, 這一階段lex會(huì)會(huì)將源代碼按照詞法規(guī)則切分一個(gè)一個(gè)的標(biāo)記(token)。PHP中提供了一個(gè)函數(shù)token_get_all(), 該函數(shù)接收一個(gè)字符串參數(shù), 返回一個(gè)按照詞法規(guī)則切分好的數(shù)組。 例如將上面的php代碼作為參數(shù)傳遞給這個(gè)函數(shù):

<?php$code =<<<PHP_CODE<?php$str = 'Hello, worldn';echo $str;PHP_CODE;var_dump(token_get_all($code));?>

運(yùn)行上面的腳本你將會(huì)看到一如下的輸出:

array ( 0 => array ( 0 => 368, // 腳本開始標(biāo)記 1 => ’<?php // 匹配到的字符串’, 2 => 1, ), 1 => array ( 0 => 371, 1 => ’ ’, 2 => 2, ), 2 => ’=’, 3 => array ( 0 => 371, 1 => ’ ’, 2 => 2, ), 4 => array ( 0 => 315, 1 => ’'Hello, world'’, 2 => 2, ), 5 => ’;’, 6 => array ( 0 => 371, 1 => ’’, 2 => 3, ), 7 => array ( 0 => 316, 1 => ’echo’, 2 => 4, ), 8 => array ( 0 => 371, 1 => ’ ’, 2 => 4, ), 9 => ’;’,

這也是Zend引擎詞法分析做的事情,將代碼切分為一個(gè)個(gè)的標(biāo)記,然后使用語(yǔ)法分析器(PHP使用bison生成語(yǔ)法分析器, 規(guī)則見$PHP_SRC/Zend/zend_language_parser。y), bison根據(jù)規(guī)則進(jìn)行相應(yīng)的處理, 如果代碼找不到匹配的規(guī)則,也就是語(yǔ)法錯(cuò)誤時(shí)Zend引擎會(huì)停止,并輸出錯(cuò)誤信息。 比如缺少括號(hào),或者不符合語(yǔ)法規(guī)則的情況都會(huì)在這個(gè)環(huán)節(jié)檢查。 在匹配到相應(yīng)的語(yǔ)法規(guī)則后,Zend引擎還會(huì)進(jìn)行編譯, 將代碼編譯為opcode, 完成后,Zend引擎會(huì)執(zhí)行這些opcode, 在執(zhí)行opcode的過(guò)程中還有可能會(huì)繼續(xù)重復(fù)進(jìn)行編譯-執(zhí)行, 例如執(zhí)行eval,include/require等語(yǔ)句, 因?yàn)檫@些語(yǔ)句還會(huì)包含或者執(zhí)行其他文件或者字符串中的腳本。

例如上例中的echo語(yǔ)句會(huì)編譯為一條ZEND_ECHO指令, 執(zhí)行過(guò)程中,該指令由C函數(shù)zend_print_variable(zval* z)執(zhí)行,將傳遞進(jìn)來(lái)的字符串打印出來(lái)。 為了方便理解, 本例中省去了一些細(xì)節(jié),例如opcode指令和處理函數(shù)之間的映射關(guān)系等。 后面的章節(jié)將會(huì)詳細(xì)介紹。

如果想直接查看生成的Opcode,可以使用php的vld擴(kuò)展查看。擴(kuò)展下載地址:?http://pecl.php.net/package/vld。Win下需要自己編譯生成dll文件。

有關(guān)PHP腳本編譯執(zhí)行的細(xì)節(jié),請(qǐng)閱讀后面有關(guān)詞法分析,語(yǔ)法分析及opcode編譯相關(guān)內(nèi)容。

標(biāo)簽: PHP
相關(guān)文章:
主站蜘蛛池模板: 9191久久久久视频 | 久久高清一级毛片 | 欧美黑人xxxxxxxxxx | 性色tv视频观看 | 欧美高清日韩 | 国产精品久久久久激情影院 | 欧美成人亚洲综合精品欧美激情 | jul-179在线中文字幕 | 欧美精品99久久久久久人 | 久久精品国产三级不卡 | 国产91会所洗浴女技师按摩 | 久 在线播放| 免费黄色网址在线播放 | 久久久综合结合狠狠狠97色 | 99精品在线免费观看 | 欧美怡红院在线观看 | 国内久久久久影院精品 | 免费欧美一级 | 国产嫩草影院在线观看 | 日本黄区 | 国产精品免费看久久久香蕉 | 国产成人黄网址在线视频 | 自拍网在线 | 黄篇网址 | 欧美日韩亚洲视频 | 日本国产一区二区三区 | 亚洲精品久久久久影院 | 亚洲精品久久99久久 | 全部免费的毛片在线看美国 | 欧美性性性性性色大片免费的 | 国产精品99久久久久久www | 日本免费一级视频 | 免费观看成年的网站 | 亚洲视频日韩 | 久久亚洲国产视频 | 日韩 国产 在线 | 目韩一区二区三区系列片丶 | 1024国产欧美日韩精品 | 白嫩美女直冒白浆 | 成人精品一区二区三区中文字幕 | 欧美一级专区免费大片 |