從最初我們編寫的
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...