国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > PHP > 正文

PHP擴(kuò)展開(kāi)發(fā)內(nèi)核執(zhí)行流程與擴(kuò)展結(jié)構(gòu)

2020-03-22 19:17:42
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
  • 在開(kāi)發(fā)擴(kuò)展之前,最好了解下PHP內(nèi)核的執(zhí)行流程,PHP大概包括三個(gè)方面:

    SAPI
    Zend VM
    內(nèi)部擴(kuò)展

    Zend VM是PHP的虛擬機(jī),與JVM類似,都是各自語(yǔ)言的編譯/執(zhí)行的核心。它們都會(huì)把各自的代碼先編譯為一種中間代碼,PHP的通常叫opcode,Java通常叫bytecode,不同的是PHP的opcode直接被Zend VM的執(zhí)行單元調(diào)用對(duì)應(yīng)的C函數(shù)執(zhí)行,不會(huì)顯示保留下來(lái)(可以cache保留),而Java通常是生成html' target='_blank'>class文件保留下來(lái)。而這一點(diǎn)可能也是PHP interpreter的名稱的由來(lái)吧。其實(shí)相對(duì)嚴(yán)格的C/C++等編譯型語(yǔ)言,PHP和Java更多的是結(jié)合了編譯型和解釋性的風(fēng)格。SAPI可以看作是Zend VM向外界提供編譯/執(zhí)行PHP代碼服務(wù)的方式和規(guī)范。無(wú)論是作為cli/cgi/fastcgi/apache_mod與其他程序交互,還是嵌入其他語(yǔ)言中如C/C++等,都可以通過(guò)SAPI的規(guī)范實(shí)現(xiàn)。它的一個(gè)重要數(shù)據(jù)結(jié)構(gòu)就是sapi_module_struct(main/SAPI.h line 217)內(nèi)部擴(kuò)展部分可以看作是搭建在Zend VM和SAPI之上的庫(kù),為PHP開(kāi)發(fā)人員提供性能和易用性上的保證。Java的各種包/Python的各種模塊功能類似,不同的是PHP中為了性能是用C擴(kuò)展來(lái)實(shí)現(xiàn)的,類似的在Java中可以通過(guò)JNI來(lái)實(shí)現(xiàn),Python中如_socket和_select(多路復(fù)用)都不是原生Python實(shí)現(xiàn)。

    生命周期

    關(guān)于各種SAPI或者PHP本身的生命周期,可能會(huì)和其他組件如apache耦合,后續(xù)再細(xì)談。關(guān)于PHP擴(kuò)展的生命周期,這里借用一張圖。流程應(yīng)該是很容易明白的,關(guān)于這個(gè)過(guò)程,網(wǎng)上也有很多資料,不再贅述。我們開(kāi)發(fā)擴(kuò)展需要注意的幾個(gè)地方也可以對(duì)應(yīng)到圖中的某些節(jié)點(diǎn):

    全局變量的定義,通常是zend_modulename_globals
    模塊的初始化,包括資源/類/常量/ini配置等模塊級(jí)的初始化
    請(qǐng)求的初始化,包括與單次請(qǐng)求相關(guān)的一些初始化
    請(qǐng)求的結(jié)束,清理單次請(qǐng)求相關(guān)的數(shù)據(jù)/內(nèi)存
    模塊的卸載,清理模塊相關(guān)的數(shù)據(jù)/內(nèi)存

    基本上我們要做的就是按照上面的流程,實(shí)現(xiàn)相關(guān)的內(nèi)置函數(shù),定義自己的資源/全局變量/類/函數(shù)等。值得注意的地方是在在嵌入其他語(yǔ)言如Python或者被嵌入其他組件如apache時(shí),要小心多進(jìn)程多線程相關(guān)的問(wèn)題。

    PHP擴(kuò)展結(jié)構(gòu)

    使用php-src/ext/ext_skel可以生成PHP擴(kuò)展的框架

    ./ext_skel --extname=myext[tan@tan ~/software/needbak/php-5.5.20/ext 12:24]$==> ls myext/config.m4  config.w32  CREDITS  EXPERIMENTAL  myext.c  myext.php  php_myext.h  tests

    比較重要的文件是config.m4(當(dāng)然還有源碼),config.m4文件可以使用phpize命令生成configure文件,其中說(shuō)明了我們是否開(kāi)啟模塊,以及外部依賴的庫(kù)。

    //config.m4//如果你的擴(kuò)展依賴其他外部庫(kù)dnl PHP_ARG_WITH(myext, for myext support,dnl Make sure that the comment is aligned:dnl [  --with-myext             Include myext support])//擴(kuò)展不依賴外部庫(kù)dnl PHP_ARG_ENABLE(myext, whether to enable myext support,dnl Make sure that the comment is aligned:dnl [  --enable-myext           Enable myext support])//尋找并包含頭文件if test "$PHP_MYEXT" != "no"; then  dnl Write more examples of tests here...  dnl # --with-myext -> check with-path  dnl SEARCH_PATH="/usr/local /usr"     # you might want to change this  dnl SEARCH_FOR="/include/myext.h"  # you most likely want to change this  dnl if test -r $PHP_MYEXT/$SEARCH_FOR; then # path given as parameter  dnl   MYEXT_DIR=$PHP_MYEXT  dnl else # search default path list  dnl   AC_MSG_CHECKING([for myext files in default path])  dnl   for i in $SEARCH_PATH ; do  dnl     if test -r $i/$SEARCH_FOR; then  dnl       MYEXT_DIR=$i  dnl       AC_MSG_RESULT(found in $i)  dnl     fi  dnl   done  dnl fi  dnl  dnl if test -z "$MYEXT_DIR"; then  dnl   AC_MSG_RESULT([not found])  dnl   AC_MSG_ERROR([Please reinstall the myext distribution])  dnl fi  dnl # --with-myext -> add include path  dnl PHP_ADD_INCLUDE($MYEXT_DIR/include)  //加載的lib位置  dnl # --with-myext -> check for lib and symbol presence  dnl LIBNAME=myext # you may want to change this  dnl LIBSYMBOL=myext # you most likely want to change this   dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,  dnl [  dnl   PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $MYEXT_DIR/$PHP_LIBDIR, MYEXT_SHARED_LIBADD)  dnl   AC_DEFINE(HAVE_MYEXTLIB,1,[ ])  dnl ],[  dnl   AC_MSG_ERROR([wrong myext lib version or lib not found])  dnl ],[  dnl   -L$MYEXT_DIR/$PHP_LIBDIR -lm  dnl ])  dnl  dnl PHP_SUBST(MYEXT_SHARED_LIBADD)  PHP_NEW_EXTENSION(myext, myext.c, $ext_shared)fi
    //php_myext.h#ifndef PHP_MYEXT_H#define PHP_MYEXT_Hextern zend_module_entry myext_module_entry;#define phpext_myext_ptr &myext_module_entry//導(dǎo)出符號(hào),在鏈接的時(shí)候有用#ifdef PHP_WIN32#   define PHP_MYEXT_API __declspec(dllexport)#elif defined(__GNUC__) && __GNUC__ >= 4#   define PHP_MYEXT_API __attribute__ ((visibility("default")))#else#   define PHP_MYEXT_API#endif#ifdef ZTS#include "TSRM.h"#endif//幾個(gè)核心函數(shù)的聲明PHP_MINIT_FUNCTION(myext);PHP_MSHUTDOWN_FUNCTION(myext);PHP_RINIT_FUNCTION(myext);PHP_RSHUTDOWN_FUNCTION(myext);PHP_MINFO_FUNCTION(myext);//自動(dòng)生成的測(cè)試函數(shù)聲明,我們自己定義的模塊函數(shù)需要在此聲明PHP_FUNCTION(confirm_myext_compiled);   //全局變量在這定義,展開(kāi)后是zend_myext_globals結(jié)構(gòu)體ZEND_BEGIN_MODULE_GLOBALS(myext)    long  global_value;    char *global_string;ZEND_END_MODULE_GLOBALS(myext)//線程安全與非線程安全下獲取全局變量的方式#ifdef ZTS#define MYEXT_G(v) TSRMG(myext_globals_id, zend_myext_globals *, v)#else#define MYEXT_G(v) (myext_globals.v)#endif#endif  /* PHP_MYEXT_H */
    //myext.c#ifdef HAVE_CONFIG_H#include "config.h"#endif#include "php.h"#include "php_ini.h"#include "ext/standard/info.h"#include "php_myext.h"http://全局變量聲明ZEND_DECLARE_MODULE_GLOBALS(myext)/* True global resources - no need for thread safety here */static int le_myext;//模塊函數(shù)的導(dǎo)出const zend_function_entry myext_functions[] = {    PHP_FE(confirm_myext_compiled,  NULL)       /* For testing, remove later. */    PHP_FE_END  /* Must be the last line in myext_functions[] */};//模塊結(jié)構(gòu)zend_module_entry myext_module_entry = {#if ZEND_MODULE_API_NO >= 20010901    STANDARD_MODULE_HEADER,#endif    "myext",    myext_functions,    PHP_MINIT(myext),    PHP_MSHUTDOWN(myext),    PHP_RINIT(myext),       /* Replace with NULL if there's nothing to do at request start */    PHP_RSHUTDOWN(myext),   /* Replace with NULL if there's nothing to do at request end */    PHP_MINFO(myext),#if ZEND_MODULE_API_NO >= 20010901    PHP_MYEXT_VERSION,#endif    STANDARD_MODULE_PROPERTIES};#ifdef COMPILE_DL_MYEXTZEND_GET_MODULE(myext)#endif//ini配置文件的設(shè)置PHP_INI_BEGIN()    STD_PHP_INI_ENTRY("myext.global_value",      "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_myext_globals, myext_globals)    STD_PHP_INI_ENTRY("myext.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_myext_globals, myext_globals)PHP_INI_END()//初始化全局變量static void php_myext_init_globals(zend_myext_globals *myext_globals){    myext_globals->global_value = 0;    myext_globals->global_string = NULL;}//模塊加載時(shí)的函數(shù)PHP_MINIT_FUNCTION(myext){    /* If you have INI entries, uncomment these lines     REGISTER_INI_ENTRIES();    */    return SUCCESS;}//模塊卸載時(shí)函數(shù)PHP_MSHUTDOWN_FUNCTION(myext){    /* uncomment this line if you have INI entries    UNREGISTER_INI_ENTRIES();    */    return SUCCESS;}//請(qǐng)求初始化函數(shù)PHP_RINIT_FUNCTION(myext){    return SUCCESS;}//請(qǐng)求關(guān)閉函數(shù)PHP_RSHUTDOWN_FUNCTION(myext){    return SUCCESS;}//模塊信息,phpinfoPHP_MINFO_FUNCTION(myext){    php_info_print_table_start();    php_info_print_table_header(2, "myext support", "enabled");    php_info_print_table_end();    /* Remove comments if you have entries in php.ini    DISPLAY_INI_ENTRIES();    */}//測(cè)試函數(shù)PHP_FUNCTION(confirm_myext_compiled){    char *arg = NULL;    int arg_len, len;    char *strg;    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {        return;    }    len = spprintf(&strg, 0, "Congratulations! You have successfully modified ext/%.78s/config.m4. Module %.78s is now compiled into PHP.", "myext", arg);    RETURN_STRINGL(strg, len, 0);}
    PHP編程

    鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

  • 發(fā)表評(píng)論 共有條評(píng)論
    用戶名: 密碼:
    驗(yàn)證碼: 匿名發(fā)表
    主站蜘蛛池模板: 桦南县| 横峰县| 庆城县| 比如县| 民乐县| 合阳县| 呼玛县| 玛沁县| 磐石市| 龙里县| 兴安盟| 大余县| 涟源市| 三原县| 江油市| 芦山县| 色达县| 广宁县| 开封县| 新宁县| 江西省| 顺平县| 独山县| 方正县| 黑山县| 苍溪县| 丰原市| 尤溪县| 宾阳县| 越西县| 勐海县| 天水市| 连城县| 上思县| 江门市| 嘉祥县| 文安县| 同德县| 饶平县| 河北区| 多伦县|