In-depth understanding of ini configuration in php (2), in-depth understanding of ini

Source: Internet
Author: User

In-depth understanding of ini configuration in php (2), in-depth understanding of ini

Continue with the previous article.

1. Change the configuration during running

As mentioned in the previous article, the ini_set function can dynamically modify some php configurations during php Execution. Note that not all configurations can be modified dynamically. For information on the modifiable ini configuration, see: http://php.net/manual/zh/configuration.changes.modes.php

We directly go to the implementation of ini_set. Although the function is a bit long, the logic is clear:

PHP_FUNCTION (ini_set) {char * varname, * new_value; int varname_len, new_value_len; char * old_value; if (convert () TSRMLS_CC, "ss", & varname, & varname_len, & new_value, & new_value_len) = FAILURE) {return;} // obtain the configured value from EG (ini_directives) old_value = zend_ini_string (varname, varname_len + 1, 0 ); /* copy to return here, because alter might free it! */If (old_value) {RETVAL_STRING (old_value, 1) ;}else {RETVAL_FALSE ;}// if security mode is enabled, the following ini configurations may involve file operations, uid # define _ CHECK_PATH (var, var_len, ini) php_ini_check_path (var, var_len, ini, sizeof (ini) needs to be checked )) /* safe_mode & basedir check */if (PG (safe_mode) | PG (open_basedir) {if (_ CHECK_PATH (varname, varname_len, "error_log ") | _ CHECK_PATH (varname, varname_len, "java. class. path ") | _ CHECK_PAT H (varname, varname_len, "java. home ") | _ CHECK_PATH (varname, varname_len," mail. log ") | _ CHECK_PATH (varname, varname_len," java. library. path ") | _ CHECK_PATH (varname, varname_len," vpopmail. directory ") {if (PG (safe_mode )&&(! Php_checkuid (new_value, NULL, success) {zval_dtor (return_value); RETURN_FALSE;} if (Response (new_value TSRMLS_CC) {zval_dtor (return_value); RETURN_FALSE ;}}} // In security mode, the following ini is protected and will not be dynamically modified if (PG (safe_mode) {if (! Strncmp ("max_execution_time", varname, sizeof ("max_execution_time") |! Strncmp ("memory_limit", varname, sizeof ("memory_limit") |! Strncmp ("child_terminate", varname, sizeof ("child_terminate") {zval_dtor (return_value); RETURN_FALSE ;}} // call supervisor to dynamically modify ini configuration if (kernel (varname, varname_len + 1, new_value, new_value_len, PHP_INI_USER, kernel, 0 TSRMLS_CC) = FAILURE) {zval_dtor (return_value ); RETURN_FALSE ;}}

We can see that in addition to some necessary verification work, the main task is to call zend_alter_ini_entry_ex.

We will continue to follow up on the zend_alter_ini_entry_ex function:

ZEND_API int partition (char * name, uint name_length, char * new_value, uint new_value_length, int modify_type, int stage, int force_change TSRMLS_DC)/* {*/{limit * ini_entry; char * duplicate; zend_bool modifiable; zend_bool modified; // find ini_entry if (e.g. (ini_directives), name, name_length, (void **) & ini_entry) = FAILURE) {return FAI LURE;} // whether or not the modifiable and modifiable = ini_entry-> modifiable; modified = ini_entry-> modified; if (stage = finished & modify_type = ZEND_INI_SYSTEM) {ini_entry-> modifiable = ZEND_INI_SYSTEM;} // whether to force modify if (! Force_change) {if (! (Ini_entry-> modifiable & modify_type) {return FAILURE; }}// EG (modified_ini_directives) is used to store the modified ini_entry
// Mainly used to restore if (! EG (modified_ini_directives) {ALLOC_HASHTABLE (EG (modified_ini_directives); zend_hash_init (EG (init), 8, NULL, NULL, 0);} // set the value in ini_entry, length of the value, which can be modified and kept in orig_xxx
// You can restore the ini_entry at the end of the request.
If (! Modified) {ini_entry-> orig_value = ini_entry-> value; ini_entry-> orig_value_length = ini_entry-> value_length; ini_entry-> metadata = modifiable; ini_entry-> modified = 1; zend_hash_add (EG (values), name, name_length, & ini_entry, sizeof (zend_ini_entry *), NULL);} duplicate = estrndup (new_value, new_value_length ); // call modify to update the corresponding ini configuration in XXX_G if (! Ini_entry-> on_modify | ini_entry-> on_modify (ini_entry, duplicate, upgrade, ini_entry-> Upgrade, stage restart) = SUCCESS) {// same as above. if you modify the value multiple times, you need to release the modified value if (modified & ini_entry-> orig_value! = Ini_entry-> value) {efree (ini_entry-> value);} ini_entry-> value = duplicate; ini_entry-> value_length = new_value_length;} else {efree (duplicate ); return FAILURE;} return SUCCESS ;}

There are three logics that need to be carefully understood:

1) The modified field in ini_entry indicates whether the configuration has been dynamically modified. Once the ini configuration is modified, the modified value is set to 1. There is a key section in the above Code:

// If you call ini_set multiple times, always keep the original value such as orig_value if (! Modified) {ini_entry-> orig_value = ini_entry-> value; ini_entry-> orig_value_length = ini_entry-> value_length; ini_entry-> metadata = modifiable; ini_entry-> modified = 1; zend_hash_add (EG (modified_ini_directives), name, name_length, & ini_entry, sizeof (zend_ini_entry *), NULL );}

This Code indicates that no matter how many times we call ini_set in the php code, the logic is entered only when ini_set is used for the first time, and the orig_value is set. Starting from the second call of ini_set, this branch will not be executed again, because the modified has been set to 1. Therefore, ini_entry-> orig_value always saves the previous configuration value (that is, the original configuration) for the first modification ).

2) The on_modify callback function is required to enable the ini_set configuration to take effect immediately.

As described in the previous article, on_modify is called to update the global variables of the module. Recall that, first, the configuration in the global variable of the module is no longer of the string type. bool and int are used for bool. Second, each ini_entry stores the address of the global variable and the corresponding offset of the module, so that on_modify can be quickly modified in memory. In addition, do not forget that after on_modify is called, you still need to update ini_entry-> value, so that the configuration value in EG (ini_directives) is the latest.

3) A new hash table (EG (modified_ini_directives) is displayed ).

EG (modified_ini_directives) is only used to store Dynamically Modified ini configurations. If an ini configuration has been dynamically modified, it is stored in EG (ini_directives, also exists in EG (modified_ini_directives. Since every ini_entry has a modified field for marking, isn't it possible to traverse EG (ini_directives) to obtain all the modified configurations?

The answer is yes. I personally think that the EG (modified_ini_directives) Here is mainly to improve the performance, it is enough to directly traverse EG (modified_ini_directives. In addition, the initialization of EG (modified_ini_directives) is postponed to zend_alter_ini_entry_ex. The detailed performance optimization points of php can also be seen.

2. Restore Configuration

The time when ini_set takes effect is different from the time when the php. ini file takes effect. Once the request execution ends, ini_set becomes invalid.. In addition, when the ini_restore function is called in our code, the configuration previously set through ini_set will also become invalid.

After each php request is executed, php_request_shutdown is triggered. php_request_startup and php_request_startup correspond to each other. If php is attached to apache/nginx, php_request_shutdown is called every time an http request is processed. If php is run in CLI mode, after the script is executed, php_request_shutdown is also called.

In php_request_shutdown, we can see the recovery for ini:

/* 7. Shutdown scanner/executor/compiler and restore ini entries */zend_deactivate(TSRMLS_C);

Go to zend_deactivate, and you can see that the zend_ini_deactivate function is called. zend_ini_deactivate is responsible for restoring the php configuration.

zend_try {    zend_ini_deactivate(TSRMLS_C);} zend_end_try();

Let's take a look at the implementation of zend_ini_deactivate:

ZEND_API int zend_ini_deactivate (TSRMLS_D)/* {*/{if (EG (modified_ini_directives) {// traverse EG (modified_ini_directives) in this table // calls zend_restore_ini_entry_wrapper zend_hash_apply (EG (batch), (apply_func_t) zend_restore_ini_entry_wrapper TSRMLS_CC) for each ini_entry; // The recycle operation zend_hash_destroy (EG (modified_ini_directives )); FREE_HASHTABLE (EG (modified_ini_directives); EG (modified_ini_directives) = NULL;} return SUCCESS ;}

From zend_hash_apply, the task of actually recovering ini is finally implemented to the zend_restore_ini_entry_wrapper callback function.

Static int enumerate (zend_ini_entry ** ini_entry TSRMLS_DC) {// encapsulate the struct (* ini_entry, struct TSRMLS_CC); return 1;} static int evaluate (zend_ini_entry * ini_entry, int stage TSRMLS_DC) {int result = FAILURE; // only check the modified ini item if (ini_entry-> modified) {if (ini_entry-> on_mod Ify) {// use orig_value to reset the relevant fields in XXX_G zend_try {result = ini_entry-> on_modify (ini_entry, ini_entry-> orig_value, ini_entry-> orig_value_length, ini_entry-> mh_arg1, ini_entry-> mh_arg2, ini_entry-> mh_arg3, stage TSRMLS_CC);} zend_end_try ();} if (stage = Success & result = FAILURE) {/* runtime failure is OK */return 1;} if (ini_entry-> value! = Ini_entry-> orig_value) {efree (ini_entry-> value);} // The ini_entry itself is restored to the original value ini_entry-> value = ini_entry-> orig_value; ini_entry-> value_length = ini_entry-> orig_value_length; ini_entry-> modifiable = ini_entry-> orig_modifiable; ini_entry-> modified = 0; ini_entry-> orig_value = NULL; ini_entry-> orig_value_length = 0; ini_entry-> orig_modifiable = 0;} return 0 ;}

The logic is quite clear. I believe readers can understand it. To sum up the ini configuration restoration process:

Php_request_shutdown ---> zend_deactivate ---> zend_ini_deactivate ---> zend_restore_ini_entry_wrapper ---> zend_restore_ini_entry_cb

3. Destroy Configuration

When the sapi lifecycle ends, for example, apache is disabled and cli is executed. At this stage, all the previously mentioned configuration_hash and EG (ini_directives) need to be destroyed, and the memory space used must be released.

1. php ends all modules in sequence and calls UNREGISTER_INI_ENTRIES in PHP_MSHUTDOWN_FUNCTION of each module. UNREGISTER_INI_ENTRIES corresponds to REGISTER_INI_ENTRIES, but UNREGISTER_INI_ENTRIES is not responsible for the global space release of the module. The memory of XXX_globals is stored in the static data area and does not need to be recycled.

UNREGISTER_INI_ENTRIES is mainly used to delete the ini_entry configuration of a module from the EG (ini_directives) table. After deletion, the ini_entry space will be recycled, but ini_entry-> value may not be recycled.

After the PHP_MSHUTDOWN_FUNCTION of all modules call UNREGISTER_INI_ENTRIES once, only the ini configuration of the Core module is left in EG (ini_directives. In this case, you need to manually call UNREGISTER_INI_ENTRIES to delete the Core module configuration.

Void php_module_shutdown (TSRMLS_D ){... // zend_shutdown will close all php modules except Core in turn // when it is closed, the PHP_MSHUTDOWN_FUNCTION zend_shutdown (TSRMLS_C) of each module will be called );... // at this point, only Core module configuration is left in EG (ini_directives) // here, manually clear UNREGISTER_INI_ENTRIES (); // reclaim configuration_hash php_shutdown_config ();
// Reclaim EG (ini_directives)
Zend_ini_shutdown (TSRMLS_C );
...}

After you manually call UNREGISTER_INI_ENTRIES, the EG (ini_directives) does not contain any elements. Theoretically, the EG (ini_directives) is an empty hash table.

2. The collection of configuration_hash occurs after EG (ini_directives). The Code posted above contains the function call of php_shutdown_config. Php_shutdown_config is mainly responsible for revoking configuration_hash.

Int php_shutdown_config (void) {// reclaim configuration_hash zend_hash_destroy (& configuration_hash);... return SUCCESS ;}

Note that zend_hash_destroy does not release the space of configuration_hash itself. Like the global space of the module accessed by XXX_G, configuration_hash is also a global variable and does not need to be recycled manually.

3. When php_shutdown_config is complete, only the space of EG (ini_directives) is not released. Therefore, the last step is to call zend_ini_shutdown. Zend_ini_shutdown is used to release EG (ini_directives ). As mentioned above, the EG (ini_directives) is theoretically an empty hash table, so the space occupied by the HashTable itself needs to be released.

ZEND_API int outputs (TSRMLS_D) {// EG (ini_direves VES) is the dynamically allocated space. zend_hash_destroy (EG (ini_directives) needs to be recycled; free (EG (ini_directives )); return SUCCESS ;}
4. Summary

Use a figure to roughly describe the process related to the ini configuration:

 

 


How to configure ini in php

Directly edit the php. ini file in the php Directory.

There is a value of "register_globals = Off", which is used to open global variables, such as the value sent from the form. If this value is set to "Off ", you can only use "$ _ POST ['variable name'], $ _ GET ['variable name']" to obtain the sent value. If it is set to "On ", you can directly use the "$ variable name" to obtain the sent value. Of course, setting it to "Off" is safer, so that data transmitted between webpages is not intercepted easily. If this value is changed to "On", it depends On your own feeling. Is it important for security or convenience?
To use mysql, remove ";" before "; extension = php_mysql.dll. All the module files are placed under the "ext" of the php decompression directory. If you use anything, just remove the previous.

How does php read the ini configuration file and display it as needed?

Do you think this meets your requirements?
<? Php // set the ini file name $ ini [0] = '1. ini '; $ ini [1] = '2. ini '; // check whether 2nd ini files exist. if not, create if (! File_exists ($ ini [1]) {$ file = fopen ($ ini [1], "a"); fwrite ($ file, '[config]'); fclose ($ file);} // get the value $ values [0] = parse_ini_file ($ ini [0]); $ values [1] = parse_ini_file ($ ini [1]); // obtain the key $ keys [0] = array_keys ($ values [0]); $ keys [1] = array_keys ($ values [1]); // write 2nd INI files if (isset ($ _ GET ['detail']) {foreach ($ keys [0] as $ key) {// if this key exists in 1st INI files, // It does not exist in 2nd INI files, then write // This is to avoid repeated or redundant write keys if ($ _ GET ['secure'] ===$ key ND! Isset ($ values [1] [$ key]) {file_put_contents ($ ini [1], "\ n $ key = 0", FILE_APPEND );}}} // obtain the value of the first ini file again $ values [1] = parse_ini_file ($ ini [1]); // obtain the keys of the 2nd INI files again $ keys [1] = array_keys ($ values [1]); // start output as table echo '<table style = "border-collapse: collapse; border: 1px solid #000000;"> '; // traverse all keys foreach ($ keys [0] as $ key) {// if the value is OK and does not exist in the second INI file, OK if ($ values [0] [$ key] = 'OK' AND! Isset ($ values [1] [$ key]) {echo '<tr style = "border: 1px solid #000000;"> '; echo '<td style = "width: 64px; border: 1px solid #000000;">', $ key, '</td> '; echo '<td style = "width: 64px; border: 1px solid #000000;"> <a href = "? Section = ', $ key,' "sty ...... remaining full text>

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.