How can PHP be extended and how can php be extended at the underlying layer of linux ?. Although most php engineers do not need to know how php's C code core works, some may know that there is a dl () function. some third-party class libraries have been used. although most php engineers do not need to know how php C code core works, some may know that there is a dl () function. or some third-party class libraries have been used, which is one of the focuses of this article.
I hope this article will help engineers who want to bring php to a wider boundary.
Let's first look at the running process of a php request:
Browser User ---> web Server (apache, nginx) ---> Zend Engine reads php code files from the file system ---> Zend interpreter works
---> Run the interpreted code --> function interfaces registered by the Zend Engine --> built-in modules or external module extensions --> back-end resources such as database memcache
Where
The function interfaces registered by the Zend Engine are various php functions that php engineers often use.
External module extensions are various so files (linux) or dll files (windwos) compiled by php ).
The content of the code browser after the explanation is returned from here.
The built-in module is the module that php will start every time it starts.
From the above flowchart, we can see that php can be expanded from three points. 1. external module extension 2 Zend Engine 3 built-in modules. I will discuss them one by one.
External module extension.
If you have used dl (), you will have access to these external extension modules. the external extension module file is stored in your hard disk. it is loaded into the memory when the php script is running and is loaded only when necessary.
After the script is run, it will be released by the memory. In general, it runs slowly but does not occupy resources. you do not need to re-compile a php.
Built-in modules
It is a module other than the Zend Engine, but it is somewhat different from the external module extension. it is already in php. it will increase the size of the php you compiled. if there is a change, you must re-compile the php. the built-in module causes
Php memory grows, but the call will be faster. in our test, some modules run in the built-in mode and the speed will be improved by more than 30%.
Zend Engine
First, I absolutely do not recommend that you modify the Zend Engine. Some php language features can be implemented only in the Zend Engine. for example, if you want to modify the name of the array keyword, you can implement it here.
In the php source code you downloaded, all codes starting with zend are related to the zend Engine.
The php source code directory structure is similar to the following:
Main php main source code,
Ext php extension
Code at the api interaction layer between sapi and different servers
Zend Engine
TSRM thread security module code
The following uses a simple module as an example to illustrate how PHP can be expanded:
First, php code has its own set of standards that you need to comply with. Otherwise, your module may not be able to release variables or other problems. These standards include macro definition and variable declaration. you can go to the official website to view details.
/* Extended standard header */
# Include "php. h"
/* Declare the so exported function */
ZEND_FUNCTION (helloworld_module );
/* Function interfaces registered by Zend Engine */
Zend_function_entry helloworldmod_interfaces [] =
{
ZEND_FE (helloworld_module, NULL)
{NULL, NULL, NULL}
};
/* This is the declared object of this module. its value plays a practical role in the module Compilation */
Zend_module_entry helloworldmod_module_entry =
{
STANDARD_MODULE_HEADER,
"Hello world ",
Helloworldmod_interfaces,
NULL,
NULL,
NULL,
NULL,
NULL,
NO_VERSION_YET,
STANDARD_MODULE_PROPERTIES
};
/* Declare an ICP filing to the zend Engine. it indicates that helloworldmod_module_entry belongs to helloworldmod. so */
# If COMPILE_DL_helloworld_module
ZEND_GET_MODULE (helloworldmod)
# Endif
/* This is the real code of the newly added function */
ZEND_FUNCTION (helloworld_module)
{
Return "Hello, world ";
}
We can modify the necessary compilation configuration information according to the config. m4 file of other extensions. This module is basically an empty config. m4 file,
Then use phpize to generate the configure file and then execute./configure & make install to compile a dynamic library.
Test. php
Echo helloworld_module ();
?>
Output:
"Hello, world"
After completing the PHP extension, we have gone deep into the php c code, but in some cases, this is not enough. We need to go deep into the c language calling c library process. a very powerful tool in linux is the LD_PRELOAD environment variable.
The LD_PRELOAD environment variable is a filter used by the compiler to find the location of the function or global variable referenced in the program. for example, you can call a method connect to Start network connection in php c code, in fact, it is through dynamic links.
Find the function connect of the c library in linux. these link files are generally placed under lib, which provides a starting point for us to affect php code execution. Because the php program will check LD_PRELOAD before dynamically loading the function connect under lib
Does the provided dynamic library have this connect function? we can interfere with php behavior here.
The following is a simple example of how to filter network access:
First, the code of the so file that is prepared as the value of the LD_PRELOAD environment variable.
Lp_demo.c
# Include
# Include
# Include
# Include
# Include
# Include
// Define our own connect function
Int connect (int sockfd, const struct sockaddr * serv_addr, socklen_t
Addrlen ){
Static int (* connect_linuxc) (int, const struct sockaddr *, socklen_t) = NULL;
Unsigned char * ip_char;
// Use the RTLD_NEXT option of lsym to bypass the connect method of the LD_PRELOAD environment variable to find the function of the c library
If (! Connect_linuxc) connect_linuxc = dlsym (RTLD_NEXT, "connect ");
Ip_char = serv_addr-> sa_data;
Ip_char + = 2;
// 192.168.2.3 found
If (* ip_char = 192) & (* (ip_char + 1) = 168) & (* (ip_char + 2) = 2) & (* (ip_char + 3) = 3 )){
// Code that returns a Permission error
Return EACCES;
}
// Call the real connect method
Return connect_linuxc (sockfd, serv_addr, addrlen );
}
Compile to so file
$ Gcc-o lp_demo.so-shared lp_demo.c-ldl
Test. php
File_get_contents ("http: // 192.168.2.3 /");
?>
Usage
LD_PRELOAD = lp_demo.so php test. php
In this way, he will not be able to access our internal website 192.168.2.3. Play a very good role in sandbox.
In addition, we can also use functions such as fwrite fopen to transfer php's read and write operations on the file system to backend resources such as mencache and nosql.
Finally, even if we have gone deep into the c library, it does not mean that we are at the bottom layer. below the c library, there are a bunch of functions starting with sys, they are the real functions in the kernel space and will not be discussed here.
Callback () function. or some third-party class libraries have been used...