深入淺出PHP Exploring PHP

2021-06-28 16:05:48 字數 2645 閱讀 6777

來自:

一直以來,橫觀國內的php現狀,很少有專門介紹php內部機制的書。呵呵,我會隨時記錄下研究的心得,有機會的時候,彙總成書。:)

今天這篇,我內心是想打算做為乙個導論:

php是乙個被廣泛應用的指令碼語言,因為它的成功,所以很多時候,我們應用php的時候是更不不需要考慮底層到底是怎麼實現的。我相信大多數的php程式 員是不會去考慮這一點的。從我接觸php開始,到今天也就是3年,這三年裡,前倆年我一直都是在」用」php,每次寫出來一段指令碼,我就會想「恩,不用擔 心,php直譯器會知道我想做什麼的」,直到去年來到雅虎,接受了乙個工作,是做乙個php的extension,從這個時候開始,我就好奇於新接觸的一 大堆的新鮮事物,zend, tsrm, zval, hashtable, op_array…

於是我到處查閱資料,每次獲得一篇好的文章,或者一段好的文字我就會如獲珍寶,列印儲存起來,細細研讀。我發現,國內關於php內部的資料真是少的可憐, 不知道是因為懂得的人多但是不願意分享,還是懂得的人本來就少,所以,這條路,我走的很辛苦。於是,就會有了這篇文章。

在這篇文章中,我會從整個php的執行期入手,大致的介紹下各個階段,詞法分析,語法分析,op code等等,以後的文章我會再詳細介紹每個階(當然,如果你急不可耐的想知道詳細,呵呵,那麼可以直接聯絡我)。

從最初我們編寫的php指令碼->到最後指令碼被執行->得到執行結果,這個過程,其實可以分為如下幾個階段(鄙視:csdn不能上圖):

首先,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,輸出結果。

圖1 處理流程

接下來,讓我們嘗試用vld來檢視一段簡單的php指令碼的中間語言。

原始**:

<?php

$i = 「this is a string「;

//i am comments

echo

$i.『 that has been echoed to screen『;

?>

採用vld得到的op codes:

filename:/home/desktop/vldoutone.php

function name: (null)

number of ops: 7

line # op fetch ext operands

2 0 fetch_w local $0, 『i『

1 assign $0, 『this+is+a+string『

4 2 fetch_r local $2, 『i『

3 concat ~3, $2,『+that+has+been+echoed+to+screen『

4 echo ~3

6 5 return 1

6 zend_handle_exception

我們可以看到,原始檔中的注釋,在op code中,已經沒有了,所以不用擔心注釋太多會影響你的指令碼執行時間(實際上,它是會影響ze的詞法處理階段的用時而已)。

現在我們來一條一條的分析這段op codes,每一條op code 又叫做一條op_line,都由如下7個部分,在zend_compile.h中,我們可以看到如下定義:

struct _zend_op ;
其中,opcode欄位指明了這操作型別,handler指明了處理器,然後有倆個運算元,和乙個操作結果。

fetch_w, 是以寫的方式獲取乙個變數,此處是獲取變數名」i」的變數於0(

∗zva

l)。將

字串」

this

+is+

a+st

ring

」賦值(

assi

gn)給

0 字串連線

顯示 可以看出,這個很類似於很多同學大學學習編譯原理時候的三元式,不同的是,這些中間**會被zend vm(zend虛擬機器)直接執行。

真正負責執行的函式是,zend_execute, 檢視zend_execute.h:

zend_api extern void (*zend_execute)(zend_op_array *op_array tsrmls_dc);

可以看出, zend_execute接受zend_op_array*作為引數。

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指令碼想要的結果。

下一次,我將介紹php變數的靈魂 – zval, 你將會看到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...