PHP扩展开发系列教程2-设置全局变量
2017-06-09 08:30 吃饱了才能撑着 阅读(52) 评论(0) 收藏 举报###背景
________________________________________
扩展经常需要一个特定的请求中由始至终跟踪一个值,而且要把它与可能同时发生的其它请求分开。
对于一般的单线程的SAPI程序来说,只要在源文件中添加一个全局变量即可。
但是对于php需要跟多线程的如 apache,nginx 等配合使用,他需要保持各个线程使用的全局数值的独立。通过使用 TSRM (Thread Safe Resource Management ,线程安全的资源管理器 ) 抽象层--有时称为 ZTS (Zend Thread Safety, Zend 线程安全),PHP将其极大的简化了。
如同任意的全局作用域,创建一个线程安全的作用域的第一步是声明它。鉴于本例的目标,你将会声明一个值为0的long型全局数值。每次hello_long()被调用,都将该值增1并返回。在php_hello.h文件中的$define PHP_HELLO_H语句后面加入下面的代码段:
#ifdef ZTS
#indlucd "TSRM.h"
#endif
ZEND_BEGIN_MODULE_GLOBALS(hello)
long counter;
ZEND_END_MODULE_GLOBALS(hello)
#ifdef ZTS
#define HELLO_G(V) TSRMG(hello_globals_id,zend_hello_globals *,v)
#else
#define HELLO_G(v) (hello_globals.v)
#endif
PHP_MINIT_FUNCTION(hello);
PHP_MSHUTDOWN_FUNCTION(hello);
PHP_RINIT_FUNCTION(hello);
接下来需要在 hello.c 中接着包含代码块后面加入下面的代码:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "php.h"
#include "php_ini.h"
#include "php_hello.h"
ZEND_DECLARE_MODULE_GLOBALS(hello)
改变 hello_module_entry 加入 PHP_RINIT(hello):
zend_module_entry hello_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
PHP_HELLO_WORLD_EXTNAME,
hello_functions,
PHP_MINIT(hello),
PHP_MSHUTDOWN(hello),
PHP_RINIT(hello),
NULL,
NULL,
#if ZEND_MODULE_API_NO >= 20010901
PHP_HELLO_WORLD_VERSION,
#endif
STANDARD_MODULE_PROPERTIES
}
而且修改你的 MINIT函数,附带着另外两个函数,它们请求启动时执行初始化:
static void php_hello_init_globals(zend_hello_globals *hello_globals){
}
PHP_RINIT_FUNCTION(hello){
HELLO_G(counter) = 0;
return SUCCESS;
}
PHP_MINI_FUNCTION(hello){
ZEND_INIT_MODULE_GLOBALS(hello,php_hello_init_globals,NULL);
REGISTER_INI_ENTRIES();
return SUCCESS;
}
最后修改自定义函数 hello_long() 函数使用这个值:
PHP_FUNCTION(hello_long){
HELLO_G(counter)++;
RETURN_LONG(HELLO_G(counter));
}
在你加入 php_hello.h的代码中,你用到了两个宏 ZEND_BEGIN_MODULE_GLOBALS() 和 ZEND_END_MODULE_GLOBALS() 用来创建一个名为 zend_hello_globals 的结构,它包含一个long型变量。然后有条件地将HELLO_G()定义为从线程池中取得数值,或者从全局作用域中得到---如果你的编译目标是非多线程。
在hello.c中,你使用 ZEND_DECLARE_MODULE_GLOBALS()宏来展示 zend_hello_globals结构,最后你在MINIT中用ZEND_INIT_MODULE_GLOBALS()分配一个线程安全的资源id.
php初学者---千锋php课堂笔记
浙公网安备 33010602011771号