PHP extension 1: PHP and Zend Overview

Source: Internet
Author: User
Tags php source code sapi variable scope
About http://devzone.zend.com/node/view/id/1021

The tutorials in this article require you to have a preliminary understanding of PHP and PHP interpreters (developed in C language.
First, confirm why we need to write a new PHP extension.
1. Because of the differences between different languages, the shared libraries developed in these languages cannot be directly called by PHP, but we really need all the functions of these shared libraries.
2. In some cases, PHP itself needs to have some unconventional features
3. We have obtained some PHP code, but we want to make it run faster, more refined and consume less resources.
4. You have developed a lot of code that needs to be sold, but you only want the buyer to have executable logic rather than source code.

There may be other reasons, but before we can create an extension, we need to first understand what is a PHP extension.

What is expansion?

As long as you are using PHP, you are already using PHP extension. Except in a few cases, all methods that can be called by all users in PHP are implemented in different PHP extensions. Most of these methods are part of the PHP standard extension. The PHP source code comes with 85 extensions. On average, each extension contains 30 methods. There are about 2500 mathematical calculation methods. However, this is still not enough. The PECL Library provides more than 100 extensions.

"If all methods are implemented by extensions, what are extensions and what are the core of PHP? ", Someone will ask.

PHP core consists of two independent parts. The bottom layer is the Zend engine, which converts programs written by programmers into identifiers that can be recognized by machines and then runs these symbols. In addition, it also completes memory management, variable scope, and specified method calls. Another part is Php core. It processes the interaction and binding at the Server Application Programming Interface (generally the runtime environment-Apache, IIS, CLI, CGI, etc.) layer. in addition, it provides checks on some items such as safe_mode and open_basedir, as well as the use of fopen (), fread () and fwrite () in user space () methods stream processing related to file systems and network I/O.

When SAPI is started, for examplePHP initializes its core subsystem in the format of/usr/local/Apache/bin/apachectl start. After this step is completed, it starts to load all the extended code one by one and calls each extendedModule initializationMethod. This method gives you the opportunity to extend the initialization of internal variables, allocate resources, register resource handles, and register methods with ze to ensure that Ze can know when a PHP script calls a method.The code to be executed.

PHP then waits for the SAPI layer to obtain a request for execution. In CGI or CLI mode, PHP can immediately obtain a request and only occurs once. In the SAPI mode of Apache, IIS, or other complete Web server, because the request is initiated by the client, this waiting-execution method can be repeated for any number of times, in addition, concurrent execution is performed in multiple cases. However, in whatever mode, PHP calls Ze to establish the runtime environment required for request execution, and then callsRequest Initialization(RINIT) Method. This method provides extensions with the opportunity to create specific environment variables, allocate requested resources, or execute other actions. A major sample of the rinit method is the use of session extension. When session. auto_start is set to enable, rinit automatically starts the session_start () method of the user space and generates the $ _ session variable.

After the request Initialization is complete, ze takes control of the program. Translate PHP code to machine-recognizable symbols and then encode them for execution. When these encodings need to call the extended definition method, ze binds the method name and parameter, and temporarily gives up control until the method call ends.

PHP calls the extendedRequest Shutdown(RSHUTDOWN) Method, so that the extension has the opportunity to clear the resources used in this call. Then, ze will execute the cleanup process (that is, garbage collection), which will very effectively use the unset () method for every variable used in this call.

After the preceding steps are completed, PHP waits for the SAPI to pass to it the next request or a stop signal. In CGI and CLI modes, the concept of "Next" does not exist, so SAPI will immediately execute shutdown. During the shutdown process, PHP calls every extendedModule Shutdown(MSHUTDOWN) Method, and finally close its core subsystem.

The above startup-execute-close process seems complicated, but it is easy to understand when you start to write an extension.

Memory Allocation

To avoid Memory leakage, ze provides its own memory management method: permanent allocation (Persistent allocation) And Non-permanent allocation (Non-persistent allocation). Permanent allocation means that the declared period of the allocated memory is longer than that of a single request. Non-permanent allocation means that when a single request ends, whether or not the free method is called, memory is recycled. For example, User-Defined variables belong to non-permanent allocation, because these variables are not of any value when the request is complete.

Although theoretically, the extension can rely on ze to automatically release the memory occupied by non-permanent variables when the request is completed, it is not recommended in actual operations. The allocated memory is not recycled for a long time, and the opened resources associated with these memories may not be properly closed, and it's like pulling the stool (make a mess) without cleaning it. As we will see, in fact, in expansion, it is easy to clear all allocated data properly.

Compare the traditional memory allocation with the permanent memory allocation and Non-permanent memory allocation used by PHP/Ze:

Traditional Non-persistent Persistent
malloc(count)
calloc(count, num)
emalloc(count)
ecalloc(count, num)
pemalloc(count, 1)*
pecalloc(count, num, 1)
strdup(str)
strndup(str, len)
estrdup(str)
estrndup(str, len)
pestrdup(str, 1)
pemalloc() & memcpy()
free(ptr) efree(ptr) pefree(ptr, 1)
realloc(ptr, newsize) erealloc(ptr, newsize) perealloc(ptr, newsize, 1)
malloc(count * num + extr)** safe_emalloc(count, num, extr) safe_pemalloc(count, num, extr)

* The pemalloc () method contains a 'persistent' identifier, which allows the pemalloc () method to be used as a non-permanent memory allocation method.
For example:Emalloc (1234) is exactly the same as pemalloc.
** Safe_emalloc () and (in PhP5) safe_pemalloc () perform additional checks to prevent integer overflow.

Establish an extended Development Environment

There are two methods for PHP extension development. The first is from the PHP source code, and the second is from the independent tools provided by PHP. The second one is relatively simple, but the disadvantage is that it can only be made into an extension form. The first option is to directly compile the new extension into the final Binary Package of PHP. The disadvantage is that it is less flexible and you have to re-compile the entire PHP source code when necessary. Therefore, we adopt 2nd methods, which are also used in most cases.

Hello World
Let's start with the most classic "Hello World. What we need to complete is an extension: it contains a method. When the method is called from a PHP script, a string "Hello world. "At the PHP script level, we can use the following implementation method: <? PHP
Function hello_world (){
Return 'Hello world ';
}
?>

Now we can implement this method in PHP extension. First, create a hello directory. To create an extension, we need to create three files: the source file containing the hello_world () method, including the header file required for PHP to call the extension and the configureation file required by the phpize tool.

Config. M4
Php_arg_enable (hello, whether to enable Hello world support,
[-- Enable-Hello enable Hello world support])

If test "$ php_hello" = "yes"; then
Ac_define (have_hello, 1, [whether you have Hello world])
Php_new_extension (hello, hello. C, $ ext_shared)
Fi
 

Php_hello.h
# Ifndef php_hello_h
# Define php_hello_h 1

# Define php_hello_world_version "1.0"
# Define php_hello_world_extname "hello"

Php_function (hello_world );

Extern zend_module_entry hello_module_entry;
# Define phpext_hello_ptr & hello_module_entry

# Endif
 

Hello. c
# Ifdef have_config_h
# Include "config. H"
# Endif

# Include "php. H"
# Include "php_hello.h"

Static function_entry hello_functions [] = ...{
Php_fe (hello_world, null)
... {Null, null, null}
};

Zend_module_entry hello_module_entry = ...{
# If zend_module_api_no> = 20010901
Standard_module_header,
# Endif
Php_hello_world_extname,
Hello_functions,
Null,
Null,
Null,
Null,
Null,
# If zend_module_api_no> = 20010901
Php_hello_world_version,
# Endif
Standard_module_properties
};

# Ifdef compile_dl_hello
Zend_get_module (Hello)
# Endif

Php_function (hello_world)
...{
Return_string ("Hello World", 1 );
}
 

As we can see, most of the above Code is glue-describes this extension to PhP and establishes communication between the extension and PHP. Only the last four lines seem to be the logic that is actually processed when a method is called. Indeed, at this level, these lines of code look very similar to the PHP code we mentioned earlier and are intuitive and easy to understand:
1. Declare a method named hello_world
2. This method returns a string with the value "Hello World ".
3. But what does 1 mean?
As we have mentioned above, ze provides its own memory management mechanism to ensure that all resources can be properly released at the end of PHP script execution. For the memory management layer, it is taboo to release the same memory twice. This is called double freeing, which is usually the cause of segmentation faults. Because it allows the program to access memory space that is no longer the program itself. Therefore, we do not want to allow Ze to release the memory space corresponding to a static string because the string is located in the whole program space and does not belong to the data block of the process. [Static data members cannot be free, because the process requires that the static data exists within the declared period of the process ]. The return_string method can assume that all strings passed to it need to be copied so that they can be safely released, but the memory is allocated to the string within the method, copying and returning are common operations. Return_string () allows us to specify whether to use string copy when calling this method. The above four lines of code are equivalent to the following code: php_function (hello_world)
{
Char * STR;

STR = estrdup ("Hello World ");
Return_string (STR, 0 );
}

In this implementation, we manually create a memory space for "hello World", and the memory space is finally passed back to the PHP script that calls it, and then the memory is handed over to return_string (), using the 0 flag indicates that return_string () does not need to create the copy of the string, we can use the existing one.


Create Extension
With the above three files, the last one is the bulid file to create an extension that can be dynamically loaded. You only need to execute three commands in the hello directory. $ Phpize
$./Configure -- enable-Hello
$ Make

After correct execution, you can see a hello. So file under Hello/modules/, which is a new PHP extension. Copy the so file to the extension directory of PHP and add a line in PHP. ini.extension=hello.soTo trigger the automatic loading of the extension when PHP starts running. For Web servers such as Apache and IIS, You need to restart the Web server. For CGI or CLI, you do not need to restart.
Run $ PHP-r 'echo hello_world ();'

If everything is normal, we can see the output Hello World on the terminal.

A similar method can be used to obtain scalar return results. For exampleRETURN_LONG()Returns an integer,RETURN_DOUBLE()Return floating point number,Return_bool () returns true/false,RETURN_NULL()Returns null. Implementation: static function_entry hello_functions [] = {
Php_fe (hello_world, null)
Php_fe (hello_long, null)
Php_fe (hello_double, null)
Php_fe (hello_bool, null)
Php_fe (hello_null, null)
{Null, null, null}
};

Php_function (hello_long)
{
Return_long (42 );
}

Php_function (hello_double)
{
Return_double (0, 3.1415926535 );
}

Php_function (hello_bool)
{
Return_bool (1 );
}

Php_function (hello_null)
{
Return_null ();
}

At the same time, we need to add the declaration of the above method in the header file php_hello.h, so that the compilation can be completed correctly.

Php_hello.h
# Ifndef php_hello_h
# Define php_hello_h 1

# Define php_hello_world_version "1.0"
# Define php_hello_world_extname "hello"

Php_function (hello_world );
Php_function (hello_long );
Php_function (hello_double );
Php_function (hello_bool );
Php_function (hello_null );

Extern zend_module_entry hello_module_entry;
# Define phpext_hello_ptr & hello_module_entry

# Endif

Then, use make to compile the new version.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.