internals:extensions

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
internals:extensions [2013/04/09 16:53] jpauliinternals:extensions [2013/04/10 12:06] jpauli
Line 123: Line 123:
 So, the first thing to remember is that an extension may behave differently if it is loaded statically against dynamically, at least if the maintainer has not taken care of such a behavior. So, the first thing to remember is that an extension may behave differently if it is loaded statically against dynamically, at least if the maintainer has not taken care of such a behavior.
  
-When you prepare your sources, part of the prepare work is to write a file //main/internal_functions.c//+When you prepare your sources, part of the prepare work is to write a file ''main/internal_functions.c''
 This files contains an array with the pointers to all the to-be-statically-compiled extensions. Here is an example : This files contains an array with the pointers to all the to-be-statically-compiled extensions. Here is an example :
 <code c> <code c>
Line 137: Line 137:
 </code> </code>
  
-Extensions such as standard are mandatory, they are always compiled and built statically.+Extensions such as ''standard'' are mandatory, they are always compiled and built statically. This is because further dynamically loaded extensions may depend on stuff provided by standard, this happens sometimes as standard provides lots of functionnality.
 **Only PHP extensions may be built statically, Zend extensions may not. Extensions which are both PHP and Zend, may be built statically** **Only PHP extensions may be built statically, Zend extensions may not. Extensions which are both PHP and Zend, may be built statically**
  
 The first thing PHP does when it loads, is to get those pointers out, and load those extensions. The first thing PHP does when it loads, is to get those pointers out, and load those extensions.
-The pointers are pointers to the zend_module_entry,, so they are PHP extensions.+The pointers are pointers to the ''zend_module_entry'', so they are PHP extensions.
  
 Example: Example:
Line 163: Line 163:
 </code> </code>
  
-To register a new PHP extension, the engine calls for zend_register_module_ex(zend_module_entry *module). +To register a new PHP extension, the engine calls for ''zend_register_module_ex(zend_module_entry *module)''
-zend_register_module_ex() does few things :+This does few things :
   * Checks for extension dependencies, but only against conflicts, so **it does not load any other extension** than the one it's been called with   * Checks for extension dependencies, but only against conflicts, so **it does not load any other extension** than the one it's been called with
   * Checks if the extension has already been registered, if it is the case, warns   * Checks if the extension has already been registered, if it is the case, warns
-  * Registers the PHP extension functions into the global function table, calling zend_register_functions(module->functions)+  * Registers the PHP extension functions into the global function table, calling ''zend_register_functions(module->functions)'' 
 + 
 +===== Parsing the ini file to get more extensions ===== 
 + 
 +''php_init_config()'' is called, it parses the different ini files (mainly php.ini) and looks for the tokens "extension=" and "zend_extension="
 +It then adds the names of the extensions to two different lists, one for PHP exts : extension_lists.functions, and one for Zend exts : extension_lists.engine. Both are zend_llist type. 
 +You can find the code by looking for the function ''php_ini_parser_cb()'' 
 + 
 +  Before PHP5.5, Zend extensions needed to be provided the full path to the extension (ini token "zend_extension="), such as /usr/lib/php/foo.so, whereas PHP extensions (using the ini token "extension=") just needed the file name and used the "extension_dir" ini directive to build the full path to load the extension. 
 +  As of 5.5, this in not the case any more and both PHP and Zend extensions are loaded providing only the file name, not the full path. 
 +   
 +At this stage, PHP and Zend extensions have been parsed from ini files, but nothing more has been done. 
 + 
 +===== Registering additionnal extensions from the SAPI module ===== 
 +Again before loading/registering anything from ini files, any SAPI may call ''php_module_startup()'' passing it an array of PHP extensions to load (pointer to zend_module_entry*) 
 +Those get registered here, the same way statically compiled got registered just few steps before, to recall : 
 +  * Checks for extension dependencies, but only against conflicts, so **it does not load any other extension** than the one it's been called with 
 +  * Checks if the extension has already been registered, if it is the case, warns 
 +  * Registers the PHP extension functions into the global function table, calling ''zend_register_functions(module->functions)'' 
 + 
 +For example, the Apache SAPI (apxs2), registers a PHP extension that provides functions related to Apache. Each SAPI may register one or more PHP extension providing additionnal functionnality for itself. Apache is a good example. 
 +  The CLI SAPI doesn't register any extension 
 +   
 +===== Loading the ini parsed extensions ===== 
 + 
 +Here comes time where PHP will effectively **load** Zend and PHP extensions, calling some hooks onto them. ''php_ini_register_extensions()'' is called and does this job. 
 +First thing to know : **Zend extensions are loaded before PHP extensions** 
 + 
 +==== Loading Zend extensions ==== 
 +''zend_load_extension()'' is called, the shared object is dlopen()'ed and two symbols are looked for : 
 +  * zend_extension_entry 
 +  * extension_version_info 
 + 
 +  If those symbols are missing, the Zend extension will fail to load 
 + 
 +Then API compatibility is checked from ''extension_version_info'' against current running PHP. Zend extension's ''api_no_check()'' may be called if mismatch. 
 +After that, buildid is checked. Buildid is a combinaison of the previously checked API number, debug flag and thread safety flag (ZTS). Other components may be used for buildid check. Zend extension's ''build_id_check()'' function may be called as well, though it's pretty uncommon. 
 + 
 +   Usually, this system just checks that the extension contains code that will be loadable and undertsnadable by the PHP internal code actually loading it. For example, an extension built with ZTS activated will hit those checks and won't be loaded on a PHP running without ZTS. 
 +    
 +After those checks, the Zend extensions get registered. ''zend_register_extension()'' is called to do this job. 
 +A message is dispatched to all previously registered Zend extension to make them know a new Zend extension is beeing registered. Then, ''message_handler()'' is called on all already registered Zend extensions, and is given as argument the pointer to the beeing-registered extension. 
 +This system has been designed so that Zend extensions may know each other, and eventually fail loading if they guess they are not compatible with each other. 
 + 
 +   Remember that there is no such thing like "dependencies" with Zend extensions. Only PHP extensions have a built-in dependency system with features we'll talk about later 
 +   
  
internals/extensions.txt · Last modified: 2017/09/22 13:28 by 127.0.0.1