PHP code architecture
All parts of PHP are in a layer called TSRM. The TSRM layer is responsible for thread security management. The bottom SAPI is external The interface that provides services, such as the command line sapi is cli, php-fpm is fastcgi's sapi, and the module mode of apache is also a sapi.
PHP kernel and Zend engine. The PHP kernel is responsible for request management/network and file operations, the Zend kernel is responsible for compilation and execution/allocation of memory and resources.
On top of all these, there is the extension layer. Most external interfaces in PHP are provided through the extension layer, for example, Language foundations such as standard and string are also provided in the form of extensions.
There are two ways to load extensions (hereinafter referred to as modules) into PHP: static compilation and dynamic linking.
Static compilation The configure script of PHP needs to be regenerated, which will not be described here. The dynamic linking method is to compile the module into a .so file and then dynamically load it into PHP.
There are two ways to load the .so file. One is to write it into the php.ini file, for example: extension=apc.so, the other is to use dl('xxx.so').
dl($library)# in the code
##The function of the function is to load a module to make its internal capabilities available. The source code of the dl() function is in the PHP source code root directory (abbreviated as PHP_SRC_HOME), PHP_SRC_HOME /ext/standard/dl.c, the key processes are as follows: PHP_FUNCTION(dl)PHPAPI PHP_FUNCTION(dl) { //... php_dl(filename, MODULE_TEMPORARY, return_value, 0 TSRMLS_CC); //... }
PHPAPI void php_dl(char *file, int type, zval *return_value, int start_now TSRMLS_DC) { if (php_load_extension(file, type, start_now TSRMLS_CC) == FAILURE) { //... }
PHPAPI int php_load_extension(char *filename, int type, int start_now TSRMLS_DC) { //文件名解析相关 //加载动态链接库 handle = DL_LOAD(libpath); //加载错误处理 //获取模块的get_module函数(重点, 模块初始入口) get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module"); //get_module函数获取错误处理 //那个get_module()得到struct zend_module_entry module_entry = get_module(); //... //注册模块(重点, 函数在这里被注册) if ((module_entry = zend_register_module_ex(module_entry TSRMLS_CC)) == NULL) { //错误处理 } //模块启动(重点, PHP_MINIT_FUNCTION) if ((type == MODULE_TEMPORARY || start_now) && zend_startup_module_ex(module_entry TSRMLS_CC) == FAILURE) { //错误处理 } //模块请求启动(重点, PHP_RINIT_FUNCTION) if ((type == MODULE_TEMPORARY || start_now) && module_entry->request_startup_func) { //错误处理 } return SUCCESS; }
function pointer from the dynamic link library just loaded, which is the get_module function we defined when developing the module.
is expanded by macro to (temporarily Ignore attributes for GNU and extern "C" for C++):zend_module_entry *get_module(void) { return &sample_module_entry; }By loading the dl() function and the module Connecting the definitions during development, we can see that when the module is loaded, our customized zend_module_entry is passed out from here. Registration of the modulemodule_entry = zend_register_module_ex(module_entry TSRMLS_CC )The above code is extracted from the function php_load_extension. We continue to drill down into zend_register_module_ex() to find the function registration we are concerned about: if (module->functions && zend_register_functions(NULL, module ->functions, NULL, module->type TSRMLS_CC)==FAILURE) {Continue to delve into the zend_register_functions function:ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) /* {{{ */ { //... //重点 如果没有函数符号表, 取全局函数符号表 if (!target_function_table) { target_function_table = CG(function_table); } //... //重点 循环zend_function_entry[] while (ptr->fname) { //向函数符号表增加函数 if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)?_function) == FAILURE) { //错误处理 } //... //准备遍历zend_function_entry[]下一个元素 ptr++; //... } //... return SUCCESS; }
//非线程安全 compiler_globals.function_table //线程安全 (((zend_compiler_globals *) (*((void ***) tsrm_ls))[ compiler_globals_id - 1])-> function_table)
Structure struct The function_table element in zend_compiler_globals is a HashTable.
The following loop is easy to understand. It is OK to add the function traversal in zend_function_entry to the HashTable during module development.Module startup/Module request startupThese two parts are easy to understand, corresponding to PHP_MINIT_FUNCTION() and PHP_RINIT_FUNCTION()in module development.
The above is the detailed content of Introduction to knowledge related to php module development. For more information, please follow other related articles on the PHP Chinese website!