PHP腳本的執(zhí)行

目前編程語言可以分為兩大類:

第一類是像C/C++捻撑, .NET, Java之類的編譯型語言番捂, 它們的共性是: 運行之前必須對源代碼進行編譯江解,然后運行編譯后的目標文件设预。
第二類比如:PHP犁河, Javascript, Ruby桨螺, Python這些解釋型語言, 他們都無需經(jīng)過編譯即可"運行"魏烫,雖然可以理解為直接運行,
但它們并不是真的直接就被能被機器理解则奥, 機器只能理解機器語言,那這些語言是怎么被執(zhí)行的呢读处, 一般這些語言都需要一個解釋器, 由解釋器來執(zhí)行這些源碼井辜, 實際上這些語言還是會經(jīng)過編譯環(huán)節(jié)管闷, 只不過它們一般會在運行的時候實時進行編譯粥脚。為了效率包个,并不是所有語言在每次執(zhí)行的時候都會重新編譯一遍, 比如PHP的各種opcode緩存擴展(如APC碧囊, xcache, eAccelerator等)天通,比如Python會將編譯的中間文件保存成pyc/pyo文件熄驼, 避免每次運行重新進行編譯所帶來的性能損失。

PHP的腳本的執(zhí)行也需要一個解釋器瓜贾, 比如命令行下的php程序,或者apache的mod_php模塊等等祭芦。 前一節(jié)提到了PHP的SAPI接口, 下面就以PHP命令行程序為例解釋PHP腳本是怎么被執(zhí)行的。 例如如下的這段PHP腳本:

<?php$str = "Hello, Tipi!\n";[echo](http://www.php.net/echo) $str;
假設上面的代碼保存在名為hello.php的文件中逊彭, 用PHP命令行程序執(zhí)行這個腳本:
$ php ./hello.php
這段代碼的輸出顯然是Hello, Tipi!侮叮, 那么在執(zhí)行腳本的時候PHP/Zend都做了些什么呢? 這些語句是怎么樣讓php輸出這段話的呢? 下面將一步一步的進行介紹审胸。

程序的執(zhí)行

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

腳本的編譯執(zhí)行

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

<?php$code =<<<PHP_CODE<?php$str = "Hello, Tipi\n";echo $str;PHP_CODE; [var_dump](http://www.php.net/var_dump)([token_get_all](http://www.php.net/token_get_all)($code));

運行上面的腳本你將會看到一如下的輸出

  0 => 
  array (
    0 => 368,       // 腳本開始標記
    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, Tipi
"',
    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引擎詞法分析做的事情硅急,將代碼切分為一個個的標記佳遂,然后使用語法分析器(PHP使用bison生成語法分析器, 規(guī)則見$PHP_SRC/Zend/zend_language_parser.y)丑罪, bison根據(jù)規(guī)則進行相應的處理凤壁, 如果代碼找不到匹配的規(guī)則跪另,也就是語法錯誤時Zend引擎會停止,并輸出錯誤信息免绿。 比如缺少括號,或者不符合語法規(guī)則的情況都會在這個環(huán)節(jié)檢查针姿。 在匹配到相應的語法規(guī)則后,Zend引擎還會進行編譯绞绒, 將代碼編譯為opcode榕暇, 完成后,Zend引擎會執(zhí)行這些opcode彤枢, 在執(zhí)行opcode的過程中還有可能會繼續(xù)重復進行編譯-執(zhí)行, 例如執(zhí)行eval缴啡,include/require等語句, 因為這些語句還會包含或者執(zhí)行其他文件或者字符串中的腳本秒咐。
例如上例中的echo語句會編譯為一條ZEND_ECHO指令, 執(zhí)行過程中携取,該指令由C函數(shù)zend_print_variable(zval* z)執(zhí)行帮孔,將傳遞進來的字符串打印出來。 為了方便理解文兢, 本例中省去了一些細節(jié),例如opcode指令和處理函數(shù)之間的映射關系等姆坚。 后面的章節(jié)將會詳細介紹。
如果想直接查看生成的Opcode烹俗,可以使用php的vld擴展查看萍程。擴展下載地址: [http://pecl.php.net/package/vld](http://pecl.php.net/package/vld)。Win下需要自己編譯生成dll文件茫负。
有關PHP腳本編譯執(zhí)行的細節(jié),請閱讀后面有關詞法分析忍法,語法分析及opcode編譯相關內(nèi)容。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末勉失,一起剝皮案震驚了整個濱河市原探,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌咽弦,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件段审,死亡現(xiàn)場離奇詭異闹蒜,居然都是意外死亡寺枉,警方通過查閱死者的電腦和手機嫂用,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甘畅,“玉大人往弓,你說我怎么就攤上這事『疲” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵顿天,是天一觀的道長。 經(jīng)常有香客問我牌废,道長,這世上最難降的妖魔是什么鸟缕? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮授段,結果婚禮上番甩,老公的妹妹穿的比我還像新娘侵贵。我一直安慰自己对室,他們只是感情好,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布蔫骂。 她就那樣靜靜地躺著牺汤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪檐迟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天溶其,我揣著相機與錄音,去河邊找鬼瓶逃。 笑死廓块,一個胖子當著我的面吹牛厢绝,可吹牛的內(nèi)容都是我干的带猴。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼靶病,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了嫡秕?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎牙甫,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窟哺,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡且轨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了旋奢。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡屉符,死狀恐怖锹引,靈堂內(nèi)的尸體忽然破棺而出矗钟,到底是詐尸還是另有隱情嫌变,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布东涡,位于F島的核電站碑宴,受9級特大地震影響软啼,放射性物質(zhì)發(fā)生泄漏延柠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一贿条、第九天 我趴在偏房一處隱蔽的房頂上張望雹仿。 院中可真熱鬧整以,春花似錦、人聲如沸公黑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至恶迈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間暇仲,已是汗流浹背副渴。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留佳晶,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓中跌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親漩符。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容