Home  >  Article  >  Backend Development  >  Introduction to knowledge related to php module development

Introduction to knowledge related to php module development

伊谢尔伦
伊谢尔伦Original
2017-06-22 13:55:391818browse

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);  
    //...   
}

php_dl

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) {  
       //...  
}

php_load_extension

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;  
}

in the process Key issues

get_module function

get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module");

After macro expansion of this code As follows:

get_module = (zend_module_entry *(*)(void)) dlsym(handle, "_get_module");

Google what the dlsym() function does, we can easily understand this A sentence of code, this is to obtain a

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 module

module_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;  
}

When obtaining the function symbol table, CG is used Macro:

target_function_table = CG(function_table);

We unravel this macro in two situations:

//非线程安全  
compiler_globals.function_table  
      
//线程安全  
(((zend_compiler_globals *) (*((void ***) tsrm_ls))[ compiler_globals_id - 1])-> function_table)

In the end, they all obtain a global

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 startup

These 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!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn