PHP底層原理____PHP

來源:互聯網
上載者:User

一、PHP底層原理--知其然知其所以然,先看一張圖

1、我們寫的PHP代碼是不能直接啟動並執行,它首先經過詞法分析器-文法分析器和編譯器

這裡你可能會覺得,PHP怎麼會是編譯性語言呢。一般認為PHP是指令碼語言,是的。但嚴格的說來,PHP也是一種編譯語言,它會將PHP編譯為opcode的一個中繼語言,有點像JAVA中的class檔案。

2、產生cpcode之後再由zend公司開發的執行引擎執行


我們來做一個比較

C、C++語言
JAVA
編譯成機器碼(二進位)來運行 先把JAVA檔案編譯成.class,被稱為bytecode,然後再用jvm來運行
所以JAVA是不可以跨平台的,而是jvm是跨平台的
解釋語言
PHP
解譯器解釋執行,最經典的如:linux shell
解譯器逐條來執行命令
PHP有特殊,雖然它是一個指令碼語言,但不是靠解譯器解釋執行。
而是zend虛擬機器屏蔽了作業系統
PHP代碼編譯成opcode.由虛擬機器來執行opcode
但是--opcode,PHP指令碼一結束,opcode就清除了(java可以將.class打包發布)

3、那麼opcode是否可以緩衝呢。

PHP本身不支援,但是apc,xcache等加速器實現了這樣的效果(如果一產生就扔掉就太浪費了)我們看看一個總結

zend編譯器(PHP->opcode)
zend虛擬機器(執行opcode)
作業系統層面 win/linux/mac

二、PHP變數的底層實現

PHP底層用C語言來實現的,C語言是強型別,而PHP是弱類型語言(如必須加上變數類型)。那麼PHP是如何?的呢。

我們解壓PHP的原始碼包,看到如下的目錄:如圖所示


我們來分析

我們開啟Zend檔案,然後找到zend.h檔案

找到

typedef struct _zval_struct zval 的結構體

再看看它的實現

struct _zval_struct {

    /* Variable information */

    zvalue_value value;     /* value */

    zend_uint refcount__gc;

    zend_uchar type;        /* active type */

    zend_uchar is_ref__gc;

}

PHP變數實現的核心就在上面的幾行代碼之中

PHP變數的值就是用上面的結構體來描述的

它由四個欄位組成

分析第一個,zvalue_value value;  

typedef union _zvalue_value { // 聯合(枚舉)

    long lval;

    double dval;

    struct {

        char *val;

        int len;

    };

    HashTable *ht;

    zend_object_value obj;

} zvalue_value;


分析第二個,zend_uchar type; 

它有可能是IS_NULL, IS_BOOL


所以判斷一個變數的類型是什麼,是根據zend_uchar type來決定的

它的值是多少是通過typedef union _zvalue_value它的聯合體來決定的


我們來分析一段代碼,看看PHP中的變數是怎麼實現的

$a = 3;/***一個結構體產生了{ union_value {long 3}  // 描述值type IS_LONG  // 描述類型refcount_gc:1is_ref_gc:0}***/

type欄位的值以常量形式存在

我們看看它具體儲存的是什麼

IS_NULL, IS_BOOL, IS_LONG, IS_DOUBLE, IS_STRING, IS_ARRARY. IS_OBJECT, IS_RESOURCE

它其實對應了PHP數組中的八種資料類型

這裡產生了一個問題,在zvalue_value中只提供了五中資料類型,下面是三種沒有對應上的類型

1: NULL直接對應zval->type=IS_NULL,就可以表示不必設定value的置
2: BOOL型,zval->type=IS_BOOL,再設定zval_value.lval = 1/0
3: Resource型,資源型往往是伺服器上開啟的一個介面,如果檔案讀取介面
zval->type=IS_RESOURCE, zval->type.lval=伺服器開啟的介面的編號
  
這裡需要我們特別注意一點:

PHP中,字串類型,長度是已經緩衝的,調用strlen不用計算,速度非常快;長度是直接放入其結構體中

$b = 'hello';/**{    {        char:'hello';        len:5;    }    type: IS_STRING;    refcount__gc:1    is_ref__gc:0}**/

再問一個問題,變數的名放在哪裡的

在PHP中,變數的名是放在符號表中的symbol_table

這裡要聞,符號表是什麼。

符號表就是一張雜湊表,裡面儲存了變數名->變數的zval結構體的地址

Zend/zend_globals.h找到HashTable synbol_table;  /* main synbol table */

雜湊表我們就可以把它作為一個關聯陣列


看一段代碼,看見聲明一個變數,就必須要想到的事情

$a = 5;$b = 5.54321;$c = 'hello';/**產生了3個結構體同時,全域富豪表中,多了3條記錄a--> 0x123 --> 結構體 {5}b--> 0x213 --> 結構體 {5.54321}c--> 0x339 --> 結構體 {hello}**/

上面是全域的符號表,一般由全域的必定有局部的符號表

HashTable *active_synbol_table

原理都是一樣的


我們再看看變數的賦值與引用,先看如下代碼:

$a = 3;

$b = $a

在底層是否產生了2個結構體呢。

是的,在PHP實現的過程中並沒有產生一個新的結構體

$a = 3/**zvalue:3type:IS_LONGrefount__gc=1is_ref_gc:0**/$b = $a/**zvalue:3type:IS_LONGrefcount__gc=2 這裡發生變化is_ref_gc:0<pre name="code" class="php">它們在地址上都指向同一個結構體,節省空間的,並沒有發生結構體的複製
**/
 




123


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.