This article studies how PHP code is interpreted and executed and the life cycle of PHP script running.
Overview
Startup of PHP service. Strictly speaking, PHP-related processes do not need to be started manually. They run when Apache starts. Of course, if you need to restart the PHP service, you can also restart the PHP service manually. For example, after updating the code in a formal environment with opcode enabled, you need to restart PHP to recompile the PHP code.
From a macro perspective, the implementation of the PHP kernel is to receive input data, perform corresponding processing internally, and then output the results. For the PHP kernel, the PHP code we write is the input data received by the kernel. After receiving the code data, the PHP kernel performs code analysis and operation execution on the code we wrote, and finally returns the corresponding operation result.
However, unlike the usual C language code, to execute PHP code, you first need to "translate" the PHP code into machine language to perform the corresponding function. To perform the "translation" step, the PHP kernel is required to perform: lexical analysis, syntax analysis and other steps. Finally, it is handed over to the Zend Engine of the PHP kernel for sequential execution.
Lexical analysis
Separate PHP code into "units" (TOKEN)
Syntax analysis
Convert "units" into operations that can be executed by Zend Engine
Zend Engine execution
Perform operations on the operations obtained by syntax analysis Sequential execution
All PHP programs (CGI/CLI) start from the SAPI (Server Application Programming Interface) interface. SAPI refers to the programming interface for specific PHP applications. For example, Apache's mod_php.
PHP will go through two main phases after it starts executing: the starting phase before processing the request and the ending phase after the request.
Starting Phase
The entire starting phase of PHP will go through two phases: module initialization and module activation.
MINIT
is the module initialization phase, which occurs during the entire life cycle after Apache/Nginx is started or during the entire execution of the command line program. This phase is only performed once
RINIT
module activation, which occurs during the request phase. Do some initialization work: such as registering constants, defining classes used by the module, etc. The module can implement these callback functions through the following macros during implementation:
PHP_MINIT_FUNCTION(myphpextension) { //注册常量或者类等初始化操作 return SUCCESS; } PHP_RINIT_FUNCTION(myphpextension) { //例如记录请求开始时间 //随后在请求结束的时候记录结束时间。这样我们就能够记录处理请求所花费时间了 return SUCCESS; }
After the PHP script request is processed, it enters the end stage. Generally, When the script is executed to the end or the exit or die function is called, PHP enters the end phase.
End phase
The end phase of PHP is divided into two parts: deactivating the module and closing the module.
RSHUTDOWN
Disable the module (corresponds to RINIT)
MSHUTDOWN
CLI/CGI mode PHP belongs to the single-process SAPI mode. This means that the PHP script is closed after being executed once, and all variables and functions cannot be used anymore. That is, in CGI mode, variables of the same php file cannot be used in other php files.
Let’s use an example to look at the SAPI life cycle of single-threaded PHP.
Single-threaded SAPI life cycle
For example:php -f test.php
Call the MINIT module of each extension to initialize
Request test.php Call the RINIT module of each extension to activate
Execute test.php
Call the RSHUTDOWN deactivation module of each extension
After executing test.php, clean up the variables and memory
Call MSHUTDOWN of each extension and close the module
Stop PHP execution
The above is a simple execution process, and some additions will be made below.
PHP will have an initialization process before calling the module initialization of each module, including:
Initializing several global variables In most cases, setting them to NULL.
Initialize several constants
Initialize Zend engine and core components
Parse php.ini
Initialization of global operation functions
Initialize statically built modules and shared modules (MINIT)
Module initialization execution operations:
Register the module to the registered module list
Register the functions contained in each module to the function table
Disable functions and classes
The zend_disable_function function will be called to represent the disable_functions variable in the PHP configuration file The function is deleted from the CG (function_table) function table.
Activate Zend engine
Use the init_compiler function to initialize the compiler.Activate SAPI
Use the sapi_activate function to initialize SG (sapi_headers) and SG (request_info), and set some content for the HTTP request method.
Environment initialization
Initialize some environment variables that need to be used in user controls. Including server environment, request data environment, etc.
Module request initialization
PHP calls the zend_activate_modules function to traverse all modules registered in the module_registry variable, and calls its RINIT method to implement the module's request initialization operation.
After processing the file-related content, PHP will call php_request_startup to do the request initialization operation:
Activate Zend engine
Activate SAPI
Environment initialization
Module request initialization
Code running
After all the above preparations are completed, Start executing the PHP program. PHP performs lexical analysis, syntax analysis and intermediate code generation operations through zend_compile_file, and returns all intermediate codes of this file. If the parsed file generates valid intermediate code, zend_excute is called to execute the intermediate code. . If exceptions occur during execution and the user has defined handling of these exceptions, these exception handling functions are called. After all operations are processed, PHP returns the result through EG (return_value_ptr_ptr).
DEACTIVATION (Close Request)
The process of PHP closing a request is a set of several closing operations. This set exists in the php_request_shutdown function. This includes:
EndCall all functions registered through register_shutdown_function(). These functions called on shutdown were added in user space.
Execute all available __destruct functions. The destructor here includes the destructor of all objects in the object pool (EG (objects_store)) and the destructor method of each element in EG (symbol_table).
Flush all output.
Send HTTP response header.
Destroy the variables of the global variable table (PG (http_globals)).
Turn off the lexical analyzer, syntax analyzer and intermediate code executor through the zend_deactivate function.
Call the post-RSHUTDOWN function of each extension. Function pointers are all NULL.
Close SAPI, destroy the contents of SG (sapi_headers), SG (request_info), etc.
Close the stream wrapper and close the stream filter.
Reset the maximum execution time.
When PHP ends a process, it calls the sapi_flush function to flush out the last content. Then it calls the zend_shutdown function to shut down the Zend engine.
The above introduces how PHP runs, including aspects of it. I hope it will be helpful to friends who are interested in PHP tutorials.