扩展全局资源和内核全局资源
在写php扩展的时候,我们需要使用一些线程全局的资源该如何操作呢?拿yaf来看看
这里定义了宏YAF_G和ZEND_DECLARE_MODULE_GLOBALS,我们先看看ZEND_DECLARE_MODULE_GLOBALS
可以看到在线程安全的环境下,ZEND_DECLARE_MODULE_GLOBALS(module_name)被定义成为ts_rsrc_id类型的,再来看看TSRMG
其中TSRMG_BULK
TSRM_UNSHUFFLE_RSRC_ID是对id进行运算,暂且不管,可以看到最终的调用者tsrm_get_ls_cache(),同样还是来看看这个函数和其内部调用的tsrm_tls_get()函数
哦, 看到这里,你会发现pthread_getspecific(),一定存在pthread_setspecific(),我们再来看看pthread_setspecific()
可以看到在分配一个新的资源的时候,会调用tsrm_tls_set(*thread_resources_ptr),而thread_resources_ptr是一个指向线程资源对象tsrm_tls_entry的数组指针,tsrm_tls_entry对象的结构体如下
可以看到真正资源数据存储在storage指针数组里,那么storage存储的是什么数据呢?
这里调用了每种资源的构造方法,看看yaf是如何来注册其全局资源对象的
可以看到它申明了zen_yaf_globals结构体对象,而其实yaf是不支持多线程环境下运行的,zen_yaf_globals只是在扩展内部使用
但是cgi, php-fpm, apache2handler是支持多线程的
这些模块中都会定义自己的析构方法,比如cgi和fpm都是php_cgi_globals_ctor,全局资源类型都是php_cgi_globals_struct
线程全局资源原理
先看下面的代码
从中可以看到pthread_setspecific会将引用类型的参数临时存起来,在thread_global_run函数里可以做一些处理,当然DEBUG模块可以处理相当复杂的业务,这里只做了简单的处理,比如其它模块间资源的共享处理,看下运行结果
当然,这里只是关于线程资源的最简单的方式,php中线程全局资源的管理由于涉及到各种资源类型的管理,比这复杂的多!