First, let’s introduce the life cycle of PHP. It should be very important for learning PHP and daily PHP development to understand what process a PHP program goes through from the beginning to the end.
Initiation and closing phases:
- The startup and shutdown phases of PHP can be divided into two levels,
- The first level is the initialization process of structures and values by the PHP interpreter as a whole.
- The second layer is during the request process of each page.
- For each extension, there will be an initialization MINT function. This process will declare variables, classes, register resources, streams and filter processors. These operations exist in all requests, so they can be called It is Persistent. Generally, the following two steps are performed:
-
REGISTER_INI_ENTRIES()
-
Initialize global variables of the module
-
After the page makes a request, PHP will establish an operating environment including the symbol table and configuration values. Then this time the PHP interpreter will cycle through each extension again and call the RINIT initialization function of each extension. The general operation of the RINT function is as follows:
-
Set globalvalue to the default value. These global variables are often required for each request, but are independent of each other for each request.
-
Those variables that need to be used need to be placed in the symbol table to prepare for calls.
-
In this function, you can also record the relevant information of the request
-
After completing the processing of the request, if the end of the script is reached or exited through die() exit(), then PHP starts cleaning up by calling RSHUTDOWN()
- At this time, the variables in each symbol table will be unset.
- When all requests are satisfied, the MSHUTDOWN process for the module begins.
-
Calling UNREGISTER_INI_ENTRYES() corresponds to the initialization process of the MINIT function.
Life cycle of PHP program execution:
To understand the life cycle, it is necessary to have some reference to the different execution methods. PHP can be executed in several different ways, each with its own specific life cycle.
- CLI: This is to execute the php program from the command line, and its life cycle is the simplest. For example, when executing test.php, the following process is experienced
-
- Figure 1 CLI execution process of PHP
- Notice that MINIT RINIT RSHUTDOWN MSHUTDOWN is only called once, which is similar to a waterfall structure.
- Multi-threaded module method: This is the most commonly used method. As an APXS module, php cooperates with apache. When apache starts, it will fork many child processes. For multiple different requests, multiple different initialization and end processes are coordinated. But for each thread, there is only one call to MINIT and MSHUTDOWN. Each request corresponds to its own separate RINIT and RSHUTDOWN.
- Multi-threaded module method: The multi-threaded method can avoid different threads from repeatedly calling MINIT/MSHUTDOWN. It has the advantage that multiple requests can share information, but the isolation requirements between requests are relatively high, otherwise it is easy An error occurred while accessing the variable.
Zend thread safety
php has a special mechanism for thread safety, called Thread Safe Resource Management (TSRM). There are obviously some differences when making thread-safe and non-thread-safe declarations:
- Thread-safe variable declaration:
-
typedef struct {
int sampleint;
char *samplestring;
} php_sample_globals;
int sample_globals_id;
PHP_MINIT_FUNCTION(sample)
{
ts_allocate_id(&sample_globals_id,
sizeof(php_sample_globals),
(ts_allocate_ctor) php_sample_globals_ctor,
(ts_allocate_dtor) php_sample_globals_dtor);
return SUCCESS;
}
- As you can see from this code, in the MINIT stage, you need to notify TSRM how much space this program requires through the ts_allocate_id function. TSRM will increase the current space consumption and return an id pointing to the corresponding part of the thread data pool.
-
When a request is made to access data, the pointer to the resource pool of the current thread is first found from the TSRM layer, and then the resource id returned by ts_allocate_id() is added as the offset.
- Non-thread-safe variable declaration:
-
typedef struct {
int sampleint;
char *samplestring;
} php_sample_globals;
php_sample_globals sample_globals;
PHP_MINIT_FUNCTION(sample)
{
php_sample_globals_ctor(&sample_globals TSRMLS_CC);
return SUCCESS;
}