摘要:引擎中定義了很多內(nèi)部函數(shù)供用戶在中使用,比如等等,除了引擎中定義的內(nèi)部函數(shù),擴(kuò)展中也提供了大量?jī)?nèi)部函數(shù),我們也可以靈活的通過(guò)擴(kuò)展自行定制。頭部是一個(gè)與完全相同的結(jié)構(gòu)函數(shù)指針,展開(kāi)
1.函數(shù)的存儲(chǔ)結(jié)構(gòu)
typedef union _zend_function zend_function; union _zend_function { zend_uchar type; struct { zend_uchar type; zend_uchar arg_flags[3]; uint32_t fn_flags; zend_string *function_name; zend_class_entry *scope; //成員方法所屬類,面向?qū)ο髮?shí)現(xiàn)中用到 union _zend_function *prototype; uint32_t num_args; //參數(shù)數(shù)量 uint32_t required_num_args; //必傳參數(shù)數(shù)量 zend_arg_info *arg_info; //參數(shù)信息 } common; zend_op_array op_array; //自定義函數(shù)(函數(shù)實(shí)際編譯為普通的zend_op_array) zend_internal_function internal_function; //內(nèi)部函數(shù)(通過(guò)擴(kuò)展或者內(nèi)核提供的C函數(shù)) };
zend_function.common.xx快速訪問(wèn)到zend_function.zend_op_array.xx及zend_function.zend_internal_function.xx zend_function.type取到zend_function.op_array.type及zend_function.internal_function.type
PHP在編譯階段將用戶自定義的函數(shù)編譯為獨(dú)立的opcodes,保存在EG(function_table)中,調(diào)用時(shí)重新分配新的zend_execute_data(相當(dāng)于運(yùn)行棧),然后執(zhí)行函數(shù)的opcodes,調(diào)用完再還原到舊的zend_execute_data,繼續(xù)執(zhí)行,EG(function_table)是一個(gè)哈希表,記錄的就是PHP中所有的函數(shù)
2.函數(shù)參數(shù)
函數(shù)參數(shù)在內(nèi)核實(shí)現(xiàn)上與函數(shù)內(nèi)的局部變量實(shí)際是一樣的,提供一個(gè)多帶帶的編號(hào),參數(shù)名稱也在zend_op_array.vars中,編號(hào)首先是從參數(shù)開(kāi)始的,所以按照參數(shù)順序其編號(hào)依次為0、1、2...(轉(zhuǎn)化為相對(duì)內(nèi)存偏移量就是96、112、128...),然后函數(shù)調(diào)用時(shí)首先會(huì)在調(diào)用位置將參數(shù)的value復(fù)制到各參數(shù)各自的位置
//參數(shù)的額外信息 typedef struct _zend_arg_info { zend_string *name; //參數(shù)名 zend_string *class_name; zend_uchar type_hint; //顯式聲明的參數(shù)類型,比如(array $param_1) zend_uchar pass_by_reference; //是否引用傳參,參數(shù)前加&的這個(gè)值就是1 zend_bool allow_null; //是否允許為NULL zend_bool is_variadic; //是否為可變參數(shù),即...用法,function my_func($a, ...$b){...} } zend_arg_info;
每個(gè)參數(shù)都有一個(gè)上面的結(jié)構(gòu),所有參數(shù)的結(jié)構(gòu)保存在zend_op_array.arg_info數(shù)組中,這里有一個(gè)地方需要注意:zend_op_array->arg_info數(shù)組保存的并不全是輸入?yún)?shù),如果函數(shù)聲明了返回值類型則也會(huì)為它創(chuàng)建一個(gè)zend_arg_info,這個(gè)結(jié)構(gòu)在arg_info數(shù)組的第一個(gè)位置,這種情況下zend_op_array->arg_info指向的實(shí)際是數(shù)組的第二個(gè)位置,返回值的結(jié)構(gòu)通過(guò)zend_op_array->arg_info[-1]讀取
3.內(nèi)部函數(shù)
內(nèi)部函數(shù)指的是由內(nèi)核、擴(kuò)展提供的C語(yǔ)言編寫的function,這類函數(shù)不需要經(jīng)歷opcode的編譯過(guò)程,所以效率上要高于PHP用戶自定義的函數(shù),調(diào)用時(shí)與普通的C程序沒(méi)有差異。Zend引擎中定義了很多內(nèi)部函數(shù)供用戶在PHP中使用,比如:define、defined、strlen、method_exists、class_exists、function_exists......等等,除了Zend引擎中定義的內(nèi)部函數(shù),PHP擴(kuò)展中也提供了大量?jī)?nèi)部函數(shù),我們也可以靈活的通過(guò)擴(kuò)展自行定制。
//zend_internal_function頭部是一個(gè)與zend_op_array完全相同的common結(jié)構(gòu) typedef struct _zend_internal_function { /* Common elements */ zend_uchar type; zend_uchar arg_flags[3]; /* bitset of arg_info.pass_by_reference */ uint32_t fn_flags; zend_string* function_name; zend_class_entry *scope; zend_function *prototype; uint32_t num_args; uint32_t required_num_args; zend_internal_arg_info *arg_info; /* END of common elements */ void (*handler)(INTERNAL_FUNCTION_PARAMETERS); //函數(shù)指針,展開(kāi):void (*handler)(zend_execute_data *execute_data, zval *return_value) struct _zend_module_entry *module; void *reserved[ZEND_MAX_RESERVED_RESOURCES]; } zend_internal_function;
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/28589.html
摘要:中專門為解決線程安全的問(wèn)題抽象出了一個(gè)線程安全資源管理器,實(shí)現(xiàn)原理比較簡(jiǎn)單既然共用資源這么困難那么就干脆不共用,各線程不再共享同一份全局變量,而是各復(fù)制一份,使用數(shù)據(jù)時(shí)各線程各取自己的副本,互不干擾。 1.線程安全資源管理器 PHP的SAPI多數(shù)是單線程環(huán)境,比如cli、fpm、cgi,每個(gè)進(jìn)程只啟動(dòng)一個(gè)主線程,這種模式下是不存在線程安全問(wèn)題的,但是也有多線程的環(huán)境,比如Apache,...
摘要:代碼的編譯的解析過(guò)程任務(wù)就是將代碼轉(zhuǎn)化為數(shù)組,代碼里的所有信息都保存在數(shù)組中,然后將數(shù)組交給引擎執(zhí)行,就是內(nèi)核具體執(zhí)行的命令,比如賦值加減操作函數(shù)調(diào)用等,每一條都對(duì)應(yīng)一個(gè)處理,這些是提前定義好的函數(shù)。 1.PHP代碼的編譯 PHP的解析過(guò)程任務(wù)就是將PHP代碼轉(zhuǎn)化為opcode數(shù)組,代碼里的所有信息都保存在opcode數(shù)組中,然后將opcode數(shù)組交給zend引擎執(zhí)行,opcode就是...
1.EG(executor_globals/zend_executor_globals) PHP整個(gè)生命周期中最主要的一個(gè)結(jié)構(gòu),是一個(gè)全局變量,在main執(zhí)行前分配(非ZTS下),直到PHP退出,它記錄著當(dāng)前請(qǐng)求全部的信息 showImg(https://segmentfault.com/img/bV8fW0?w=960&h=777); 2.EX(execute_data/zend_execut...
摘要:父類方法為錯(cuò)誤,成員方法不得被重寫。父子類方法靜態(tài)屬性不一致父類方法為非靜態(tài)而子類的是靜態(tài)或相反,錯(cuò)誤。 1.類的結(jié)構(gòu) 類是編譯階段的產(chǎn)物,而對(duì)象是運(yùn)行時(shí)產(chǎn)生的,它們歸屬于不同階段。編譯完成后我們定義的每個(gè)類都會(huì)生成一個(gè)zend_class_entry,它保存著類的全部信息,在執(zhí)行階段所有類相關(guān)的操作都是用的這個(gè)結(jié)構(gòu), struct _zend_class_entry { ch...
閱讀 1128·2021-08-12 13:24
閱讀 2974·2019-08-30 14:16
閱讀 3301·2019-08-30 13:01
閱讀 2064·2019-08-30 11:03
閱讀 2768·2019-08-28 17:53
閱讀 3079·2019-08-26 13:50
閱讀 2263·2019-08-26 12:00
閱讀 942·2019-08-26 10:38