深入淺出PHP(Exploring PHP)

2021-07-04 19:04:19 字數 3517 閱讀 3429

從最初我們編寫的

php指令碼

->

到最後指令碼被執行

->

得到執行結果,這個過程,其實可以分為如下幾個階段:

首先,zend engine(ze)

,呼叫詞法分析器

(lex

生成的,原始檔在

zend/zend_language_sanner.l),

將我們要執行的

php原始檔,去掉空格

,注釋,分割成乙個乙個的

token。

然後,ze

會將得到的

token forward

給語法分析器

(yacc

生成,

原始檔在

zend/zend_language_parser.y)

,生成乙個乙個的

op code

,opcode

一般會以

op array

的形式存在,它是

php執行的中間語言。

最後,ze呼叫

zend_executor

來執行op array

,輸出結果。

處理流程 ze

是乙個虛擬機器,正是由於它的存在,所以才能使得我們寫

php指令碼,完全不需要考慮所在的作業系統型別是什麼。

ze是乙個

cisc

(複雜指令處理器),

它支援150

條指令(具體指令在

zend/zend_vm_opcodes.h

),包括從最簡單的

zend_echo(echo)

到複雜的

zend_include_or_eval(include,require)

,所有我們編寫的

php都會最終被處理為這

150條指令

(op code)

的序列,從而最終被執行。

那有什麼辦法可以看到我們的

php指令碼,最終被「翻譯

」成什麼樣的呢?

也就是說,

op code

張的什麼樣子呢?

呵呵,達到這個,我們需要重新編譯

php,修改它的

compile_file

和zend_execute

函式。不過,在

pecl

中已經有這樣的模組,可以

讓我們直接使用了,那就是由

derick rethans

開發的vld (vulcan logic dissassembler)

php中,就可以通過簡單的設定,來得到指令碼翻譯的結果了。具體關於這個模組的使用說

明-雅虎一下,你就知道

^_^。

接下來,讓我們嘗試用

vld來檢視一段簡單的

php指令碼的中間語言。

原始**:

<?php $i

= 「this is a string「;

//i am comments

echo$i.

『thathas been echoed to screen『;

?> 採用

vld得到的

op codes:

filename

:/home

/desktop

/vldoutone

.php

function

name: (

null)

number

ofops: 7

line

#  op                fetch       ext  operands

——————————————————————————————————————————- 2

0fetch_w

local$0

, 『i『

1assign$0

, 『this+is+a+string『

42fetch_r

local$2

, 『i『

3concat~3

, $2,『

+that+has+been+echoed+to+screen『

4echo~3

65return1

6zend_handle_exception

我們可以看到,原始檔中的注釋,在

op code

中,已經沒有了,所以不用擔心注釋太多會影響你的指令碼執行時間(實際上,它是會影響

ze的詞法處理階段的用時而已)。

現在我們來一條一條的分析這段

op codes

,每一條

op code

又叫做一條

op_line

,都由如下

7個部分,在

zend_compile.h

中,我們可以看到如下定義:

struct

_zend_op;

其中,opcode

字段指明了這操作型別,

handler

指明了處理器,然後有倆個運算元,和乙個操作結果。

1.       

fetch_w,

是以寫的方式獲取乙個變數,此處是獲取變數名

」i」的變數於$0(

*zval)。

2.       

將字串

」this+is+a+string」

賦值(assign)給$0

3.       

字串連線

4.       顯示

可以看出,這個很類似於很多同學大學學習編譯原理時候的三元式,不同的是,這些中間**會被

zend vm

(zend

虛擬機器)直接執行。

真正負責執行的函式是,

zend_execute,

檢視zend_execute.h:

1.       

zend_api

extern

void

(*zend_execute)(zend_op_array *op_array tsrmls_dc);

可以看出,

zend_execute

接受zend_op_array*

作為引數。

1.       

struct _zend_op_array ;

可以看到,

zend_op_array

的結構和

zend_function

的結構很像(參看我的其他文章),

對於在全域性作用域的**,就是不包含在任何

function

內的op_array,

它的function_name

為null

。結構中的

opcodes

儲存了屬於這個

op_array

的op code

陣列,zend_execute

會從start_op

開始,逐條解釋執行傳入的每條

op code,

從而實現我們

php指令碼想要的結果。

深入淺出sizeof

int佔 位元組,short佔 位元組 1.0 回答下列問題 答案在文章末尾 1.sizeof char 2.sizeof a 3.sizeof a 4.strlen a 如果你答對了全部四道題,那麼你可以不用細看下面關於sizeof的論述。如果你答錯了部分題目,那麼就跟著我來一起 關於sizeof...

深入淺出ShellExecute

ipconfig c log.txt應如何處理?二樓的朋友,開啟拔號網路這樣 shellexecute null,open c windows rundll32.exe shell32.dll,control rundll c windows system telephon.cpl null,sw ...

深入淺出ShellExecute

深入淺出shellexecute譯者 徐景周 原作 nishant s q 如何開啟乙個應用程式?shellexecute this m hwnd,open calc.exe sw show 或shellexecute this m hwnd,open notepad.exe c mylog.log...