PHP扩展开发-内核执行流程与扩展结构
Jun 23, 2016 pm 01:38 PM
在开发扩展之前,最好了解下PHP内核的执行流程,PHP大概包括三个方面:
SAPI
Zend VM
内部扩展
生命周期
关于各种SAPI或者PHP本身的生命周期,可能会和其他组件如apache耦合,后续再细谈。关于PHP扩展的生命周期,这里借用一张图。流程应该是很容易明白的,关于这个过程,网上也有很多资料,不再赘述。我们开发扩展需要注意的几个地方也可以对应到图中的某些节点:
全局变量的定义,通常是zend_modulename_globals
模块的初始化,包括资源/类/常量/ini配置等模块级的初始化
请求的初始化,包括与单次请求相关的一些初始化
请求的结束,清理单次请求相关的数据/内存
模块的卸载,清理模块相关的数据/内存
基本上我们要做的就是按照上面的流程,实现相关的内置函数,定义自己的资源/全局变量/类/函数等。值得注意的地方是在在嵌入其他语言如Python或者被嵌入其他组件如apache时,要小心多进程多线程相关的问题。
PHP扩展结构
使用php-src/ext/ext_skel可以生成PHP扩展的框架
./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(当然还有源码),config.m4文件可以使用phpize命令生成configure文件,其中说明了我们是否开启模块,以及外部依赖的库。
//config.m4//如果你的扩展依赖其他外部库dnl PHP_ARG_WITH(myext, for myext support,dnl Make sure that the comment is aligned:dnl [ --with-myext Include myext support])//扩展不依赖外部库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//导出符号,在链接的时候有用#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//几个核心函数的声明PHP_MINIT_FUNCTION(myext);PHP_MSHUTDOWN_FUNCTION(myext);PHP_RINIT_FUNCTION(myext);PHP_RSHUTDOWN_FUNCTION(myext);PHP_MINFO_FUNCTION(myext);//自动生成的测试函数声明,我们自己定义的模块函数需要在此声明PHP_FUNCTION(confirm_myext_compiled); //全局变量在这定义,展开后是zend_myext_globals结构体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"//全局变量声明ZEND_DECLARE_MODULE_GLOBALS(myext)/* True global resources - no need for thread safety here */static int le_myext;//模块函数的导出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[] */};//模块结构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配置文件的设置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;}//模块加载时的函数PHP_MINIT_FUNCTION(myext){ /* If you have INI entries, uncomment these lines REGISTER_INI_ENTRIES(); */ return SUCCESS;}//模块卸载时函数PHP_MSHUTDOWN_FUNCTION(myext){ /* uncomment this line if you have INI entries UNREGISTER_INI_ENTRIES(); */ return SUCCESS;}//请求初始化函数PHP_RINIT_FUNCTION(myext){ return SUCCESS;}//请求关闭函数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(); */}//测试函数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);}

Article chaud

Outils chauds Tags

Article chaud

Tags d'article chaud

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

11 meilleurs scripts de raccourcissement d'URL PHP (gratuit et premium)

Travailler avec les données de session Flash dans Laravel

Misque de réponse HTTP simplifié dans les tests Laravel

Curl dans PHP: Comment utiliser l'extension PHP Curl dans les API REST

Construisez une application React avec un Laravel Back End: Partie 2, React

12 meilleurs scripts de chat PHP sur Codecanyon
