suchen
Heimphp教程php手册Ändern Sie die INI-Konfiguration in den php_php-Grundlagen dynamisch

1, Konfiguration während der Laufzeit ändern
Wie im vorherigen Artikel erwähnt, kann die Funktion ini_set einige PHP-Konfigurationen während der Ausführung von PHP dynamisch ändern. Beachten Sie, dass dies nur ein Teil davon ist und nicht alle Konfigurationen dynamisch geändert werden können. Informationen zur änderbaren INI-Konfiguration finden Sie unter: http://php.net/manual/zh/configuration.changes.modes.php

Wir betreten direkt die Implementierung von ini_set. Obwohl die Funktion etwas lang ist, ist die Logik sehr klar:

Code kopieren Der Code lautet wie folgt:

PHP_FUNCTION(ini_set)
{
char *varname, *new_value;
int varname_len, new_value_len;
char *old_value;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &varname, &varname_len, &new_value, &new_value_len) == FAILURE) {
         zurück;
}

// Den konfigurierten Wert von EG (ini_directives) abrufen
Old_value = zend_ini_string(varname, varname_len + 1, 0);

/* kopieren, um hierher zurückzukehren, da alter es möglicherweise freigibt */
If (old_value) {
RETVAL_STRING(old_value, 1);
} sonst {
RETVAL_FALSE;
}

// Wenn der abgesicherte Modus aktiviert ist, können die folgenden INI-Konfigurationen Dateivorgänge beinhalten und Sie müssen die UID überprüfen
#define _CHECK_PATH(var, var_len, ini) php_ini_check_path(var, var_len, ini, sizeof(ini))
/* Safe_Mode & BasedIR-Prüfung */
If (PG(safe_mode) || PG(open_basedir)) {
If (_CHECK_PATH(varname, varname_len, "error_log") ||
​​​​​​ _CHECK_PATH(varname, varname_len, "java.class.path") ||
​​​​​​ _CHECK_PATH(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, CHECKUID_CHECK_FILE_AND_DIR))) {
                   zval_dtor(return_value);
RETURN_FALSE;
            }
If (php_check_open_basedir(new_value TSRMLS_CC)) {
                   zval_dtor(return_value);
RETURN_FALSE;
            }
}
}

// Im abgesicherten Modus sind die folgenden INIs geschützt und werden nicht dynamisch geändert
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;
}
}

// Zend_alter_ini_entry_ex aufrufen, um die INI-Konfiguration dynamisch zu ändern
If (zend_alter_ini_entry_ex(varname, varname_len + 1, new_value, new_value_len, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0 TSRMLS_CC) == FAILURE) {
          zval_dtor(return_value);
RETURN_FALSE;
}
}

Comme vous pouvez le constater, en plus de quelques travaux de vérification nécessaires, l'essentiel est d'appeler zend_alter_ini_entry_ex.

Nous continuons le suivi dans la fonction zend_alter_ini_entry_ex :

Copier le code Le code est le suivant :

ZEND_API int zend_alter_ini_entry_ex(char *name, uint name_length, char *new_value, uint new_value_length, int modifier_type, int stage, int force_change TSRMLS_DC) /* {{{ */
{
zend_ini_entry *ini_entry;
char *dupliquer ;
zend_bool modifiable ;
zend_bool modifié ;

// Trouver l'ini_entry
correspondant dans EG (ini_directives) If (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry) == FAILURE) {
        return FAILURE ;
>

// S'il a été modifié et s'il peut être modifié
Modifiable = ini_entry->modifiable;
Modifié = ini_entry->modifié;

if (stage == ZEND_INI_STAGE_ACTIVATE && modifier_type == ZEND_INI_SYSTEM) {
ini_entry->modifiable = ZEND_INI_SYSTEM;
>

// Faut-il forcer la modification
Si (!force_change) {
Si (!(ini_entry->modifiable & modifier_type)) {
              return FAILURE ;
>
>

// EG (modified_ini_directives) est utilisé pour stocker l'ini_entry modifié
// Principalement utilisé pour la récupération
Si (!EG(modified_ini_directives)) {
ALLOC_HASHTABLE(EG(modified_ini_directives));
        zend_hash_init(EG(modified_ini_directives), 8, NULL, NULL, 0);
>
 
//Réservez la valeur dans ini_entry, la longueur de la valeur et la plage modifiable dans orig_xxx
// Pour que ini_entry puisse être restauré à la fin de la requête
Si (!modifié) {
ini_entry->orig_value = ini_entry->value;
ini_entry->orig_value_length = ini_entry->value_length;
ini_entry->orig_modifiable = modifiable;
ini_entry->modifié = 1;
        zend_hash_add(EG(modified_ini_directives), nom, nom_longueur, &ini_entry, sizeof(zend_ini_entry*), NULL);
>

duplicate = estrndup(new_value, new_value_length);

// Appel modifier pour mettre à jour la configuration ini correspondante dans XXX_G
if (!ini_entry->on_modify || ini_entry->on_modify(ini_entry, duplicate, new_value_length, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage TSRMLS_CC) == SUCCÈS) {
                 // Comme ci-dessus, si elle est modifiée plusieurs fois, la valeur précédemment modifiée doit être libérée
Si (modifié && ini_entry->orig_value != ini_entry->value) {
              efree(ini_entry->value);
>
ini_entry->value = dupliquer;
ini_entry->value_length = new_value_length;
} autre {
        efree(duplicata);
        return FAILURE ;
>

retour SUCCÈS ;
>

Il y a 3 logiques que nous devons bien comprendre :

1) Le champ modifié dans ini_entry est utilisé pour indiquer si la configuration a été modifiée dynamiquement. Une fois la configuration ini modifiée, modifié sera défini sur 1. Il y a une section cruciale dans le code ci-dessus :

Copier le code Le code est le suivant :

// Si ini_set est appelé plusieurs fois, orig_value, etc. conservez toujours la valeur d'origine
si (!modifié) {
ini_entry->orig_value = ini_entry->value;
ini_entry->orig_value_length = ini_entry->value_length;
ini_entry->orig_modifiable = modifiable;
ini_entry->modifié = 1;
zend_hash_add(EG(modified_ini_directives), nom, nom_longueur, &ini_entry, sizeof(zend_ini_entry*), NULL);
>

Ce code signifie que peu importe le nombre de fois que nous appelons ini_set dans le code php, seul le premier ini_set entrera dans cette logique et définira la valeur orig_value. A partir du deuxième appel à ini_set, cette branche ne sera plus exécutée car modifiée à ce moment a été mise à 1. Par conséquent, ini_entry->orig_value enregistre toujours la valeur de configuration avant la première modification (c'est-à-dire la configuration la plus originale).

2) Afin que la configuration modifiée par ini_set prenne effet immédiatement, la fonction de rappel on_modify est requise.

Comme mentionné dans l'article précédent, on_modify est appelé pour pouvoir mettre à jour les variables globales du module. Rappelez-vous encore une fois, tout d'abord, la configuration dans les variables globales du module n'est plus de type chaîne. Utilisez bool lorsqu'il doit utiliser bool, et int lorsqu'il doit utiliser int. Deuxièmement, chaque ini_entry stocke l'adresse de la variable globale du module et le décalage correspondant, afin que on_modify puisse modifier rapidement la mémoire. De plus, n'oubliez pas qu'après l'appel de on_modify, ini_entry->value doit encore être mis à jour afin que la valeur de configuration dans EG (ini_directives) soit la plus récente.

3) Une nouvelle table de hachage apparaît ici, EG (modified_ini_directives).

EG (modified_ini_directives) est uniquement utilisé pour stocker les configurations ini modifiées dynamiquement. Si une configuration ini est modifiée dynamiquement, alors elle existe à la fois dans EG (ini_directives) et EG (modified_ini_directives). Puisque chaque ini_entry est marqué d'un champ modifié, n'est-il pas possible de parcourir EG (ini_directives) pour obtenir toutes les configurations modifiées ?

La réponse est oui. Personnellement, je pense que l'EG (modified_ini_directives) ici sert principalement à améliorer les performances. Il suffit de parcourir directement l'EG (modified_ini_directives). De plus, en différant l'initialisation de EG (modified_ini_directives) à zend_alter_ini_entry_ex, vous pouvez également voir les points d'optimisation des performances de PHP en détail.

2, restaurer la configuration
Le temps d'action de ini_set est différent de celui du fichier php.ini. Une fois l'exécution de la requête terminée, ini_set deviendra invalide. De plus, lorsque la fonction ini_restore est appelée dans notre code, la configuration précédemment définie via ini_set deviendra également invalide.

Après l'exécution de chaque requête php, php_request_shutdown sera déclenché et php_request_startup sont deux processus correspondants. Si php est connecté sous Apache/nginx, php_request_shutdown sera appelé à chaque fois qu'une requête http est traitée ; si php est exécuté en mode CLI, php_request_shutdown sera également appelé après l'exécution du script.

Dans php_request_shutdown, nous pouvons voir le processus de récupération pour ini :

Copier le code Le code est le suivant :

/* 7. Arrêtez le scanner/l'exécuteur/le compilateur et restaurez les entrées ini */
zend_deactivate(TSRMLS_C);

Entrez zend_deactivate, vous pouvez voir en outre que la fonction zend_ini_deactivate est appelée et que zend_ini_deactivate est responsable de la restauration de la configuration php.

Copier le code Le code est le suivant :

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

Regardons de plus près l'implémentation de zend_ini_deactivate :

Copier le code Le code est le suivant :

ZEND_API int zend_ini_deactivate(TSRMLS_D) /* {{{ */
{
If (EG(modified_ini_directives)) {
// Diese Tabelle in EG durchlaufen (modified_ini_directives)
// Zend_restore_ini_entry_wrapper
für jeden ini_entry aufrufen         zend_hash_apply(EG(modified_ini_directives), (apply_func_t) zend_restore_ini_entry_wrapper TSRMLS_CC);
         
             // Recyclingbetrieb
        zend_hash_destroy(EG(modified_ini_directives));
FREE_HASHTABLE(EG(modified_ini_directives));
        EG(modified_ini_directives) = NULL;
}
Rückgabe ERFOLGREICH;
}

Von zend_hash_apply fällt die eigentliche Aufgabe der Wiederherstellung von INI schließlich auf die Callback-Funktion zend_restore_ini_entry_wrapper.

Code kopieren Der Code lautet wie folgt:

static int zend_restore_ini_entry_wrapper(zend_ini_entry **ini_entry TSRMLS_DC)
{
// zend_restore_ini_entry_wrapper ist die Kapselung von zend_restore_ini_entry_cb
zend_restore_ini_entry_cb(*ini_entry, ZEND_INI_STAGE_DEACTIVATE TSRMLS_CC);
Rückgabe 1;
}

static int zend_restore_ini_entry_cb(zend_ini_entry *ini_entry, int stage TSRMLS_DC)
{
int result = FAILURE;

// Nur geänderte INI-Elemente anzeigen
If (ini_entry->modified) {
If (ini_entry->on_modify) {
//Orig_value verwenden, um die relevanten Felder in XXX_G
zurückzusetzen             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 == ZEND_INI_STAGE_RUNTIME && result == FAILURE) {
                    /* Laufzeitfehler ist in Ordnung */
              return 1;
}
If (ini_entry->value != ini_entry->orig_value) {
              efree(ini_entry->value);
}
         
​​​​ // ini_entry selbst wird auf seinen ursprünglichen Wert zurückgesetzt
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;
}
Rückgabe 0;
}

Die Logik ist ziemlich klar, ich glaube, dass die Leser sie verstehen können. Um den Wiederherstellungsprozess der INI-Konfiguration zusammenzufassen:

Code kopieren Der Code lautet wie folgt:

php_request_shutdown--->zend_deactivate--->zend_ini_deactivate--->zend_restore_ini_entry_wrapper--->zend_restore_ini_entry_cb

3. Zerstörung der Konfiguration
Am Ende des Sapi-Lebenszyklus wird beispielsweise Apache heruntergefahren, das CLI-Programm ausgeführt usw. Sobald diese Phase erreicht ist, müssen der zuvor erwähnte Konfigurations-Hash, EG (ini_directives) usw. zerstört und der von ihnen verwendete Speicherplatz freigegeben werden.

1. PHP beendet alle Module nacheinander und ruft UNREGISTER_INI_ENTRIES in PHP_MSHUTDOWN_FUNCTION jedes Moduls auf. UNREGISTER_INI_ENTRIES entspricht REGISTER_INI_ENTRIES, aber UNREGISTER_INI_ENTRIES ist nicht für die Freigabe des globalen Speicherplatzes des Moduls verantwortlich. Der Speicher von XXX_globals wird im statischen Datenbereich platziert und muss nicht manuell recycelt werden.

Die Hauptaufgabe von UNREGISTER_INI_ENTRIES besteht darin, die ini_entry-Konfiguration eines bestimmten Moduls aus der EG-Tabelle (ini_directives) zu löschen. Nach dem Löschen wird der Speicherplatz von ini_entry selbst zurückgefordert, ini_entry->value darf jedoch nicht zurückgefordert werden.

Nachdem PHP_MSHUTDOWN_FUNCTION aller Module einmal UNREGISTER_INI_ENTRIES aufgerufen hat, bleibt nur noch die INI-Konfiguration des Core-Moduls in EG übrig (ini_directives). Zu diesem Zeitpunkt müssen Sie UNREGISTER_INI_ENTRIES manuell aufrufen, um das Löschen der Kernmodulkonfiguration abzuschließen.

Code kopieren Der Code lautet wie folgt:

void php_module_shutdown(TSRMLS_D)
{
...
 
// zend_shutdown fährt nacheinander alle PHP-Module außer Core herunter
// PHP_MSHUTDOWN_FUNCTION
jedes Moduls wird beim Schließen aufgerufen zend_shutdown(TSRMLS_C);
 
...

// Zu diesem Zeitpunkt ist nur noch die Konfiguration des Core-Moduls in EG (ini_directives) übrig
// Hier manuell bereinigen
UNREGISTER_INI_ENTRIES();
 
// Konfigurationshash recyceln
php_shutdown_config();

// EG(ini_directives) recyceln
zend_ini_shutdown(TSRMLS_C);

...
}

Nachdem der manuelle Aufruf von UNREGISTER_INI_ENTRIES abgeschlossen ist, enthält EG (ini_directives) keine Elemente mehr. Theoretisch ist EG (ini_directives) zu diesem Zeitpunkt eine leere Hash-Tabelle.

2. Das Recycling von „configuration_hash“ erfolgt nach EG (ini_directives). Der oben gepostete Code enthält den Funktionsaufruf über php_shutdown_config. php_shutdown_config ist hauptsächlich für das Recycling von Configuration_Hash verantwortlich.

Code kopieren Der Code lautet wie folgt:

int php_shutdown_config(void)
{
// Konfigurationshash recyceln
zend_hash_destroy(&configuration_hash);
 
...
 
Rückgabe ERFOLGREICH;
}

Beachten Sie, dass zend_hash_destroy den Speicherplatz von „configuration_hash“ selbst nicht freigibt. Ebenso wie der globale Speicherplatz des Moduls, auf den XXX_G zugreift, ist auch „configuration_hash“ eine globale Variable und muss nicht manuell recycelt werden.

3. Wenn php_shutdown_config abgeschlossen ist, wurde nur der eigene Speicherplatz von EG (ini_directives) nicht freigegeben. Der letzte Schritt ruft also zend_ini_shutdown auf. zend_ini_shutdown wird verwendet, um EG (ini_directives) freizugeben. Wie oben erwähnt, handelt es sich bei EG (ini_directives) zu diesem Zeitpunkt theoretisch um eine leere Hash-Tabelle, sodass der von der HashTable selbst belegte Speicherplatz freigegeben werden muss.

Code kopieren Der Code lautet wie folgt:

ZEND_API int zend_ini_shutdown(TSRMLS_D)
{
// EG (ini_directives) wird dynamisch Speicherplatz zugewiesen und muss recycelt werden
zend_hash_destroy(EG(ini_directives));
free(EG(ini_directives));
Rückgabe ERFOLGREICH;
}

4, Zusammenfassung
Verwenden Sie ein Bild, um den Prozess im Zusammenhang mit der INI-Konfiguration grob zu beschreiben:

Ändern Sie die INI-Konfiguration in den php_php-Grundlagen dynamisch

Stellungnahme
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
php怎么把负数转为正整数php怎么把负数转为正整数Apr 19, 2022 pm 08:59 PM

php把负数转为正整数的方法:1、使用abs()函数将负数转为正数,使用intval()函数对正数取整,转为正整数,语法“intval(abs($number))”;2、利用“~”位运算符将负数取反加一,语法“~$number + 1”。

php怎么实现几秒后执行一个函数php怎么实现几秒后执行一个函数Apr 24, 2022 pm 01:12 PM

实现方法:1、使用“sleep(延迟秒数)”语句,可延迟执行函数若干秒;2、使用“time_nanosleep(延迟秒数,延迟纳秒数)”语句,可延迟执行函数若干秒和纳秒;3、使用“time_sleep_until(time()+7)”语句。

php字符串有没有下标php字符串有没有下标Apr 24, 2022 am 11:49 AM

php字符串有下标。在PHP中,下标不仅可以应用于数组和对象,还可应用于字符串,利用字符串的下标和中括号“[]”可以访问指定索引位置的字符,并对该字符进行读写,语法“字符串名[下标值]”;字符串的下标值(索引值)只能是整数类型,起始值为0。

php怎么除以100保留两位小数php怎么除以100保留两位小数Apr 22, 2022 pm 06:23 PM

php除以100保留两位小数的方法:1、利用“/”运算符进行除法运算,语法“数值 / 100”;2、使用“number_format(除法结果, 2)”或“sprintf("%.2f",除法结果)”语句进行四舍五入的处理值,并保留两位小数。

php怎么读取字符串后几个字符php怎么读取字符串后几个字符Apr 22, 2022 pm 08:31 PM

在php中,可以使用substr()函数来读取字符串后几个字符,只需要将该函数的第二个参数设置为负值,第三个参数省略即可;语法为“substr(字符串,-n)”,表示读取从字符串结尾处向前数第n个字符开始,直到字符串结尾的全部字符。

php怎么根据年月日判断是一年的第几天php怎么根据年月日判断是一年的第几天Apr 22, 2022 pm 05:02 PM

判断方法:1、使用“strtotime("年-月-日")”语句将给定的年月日转换为时间戳格式;2、用“date("z",时间戳)+1”语句计算指定时间戳是一年的第几天。date()返回的天数是从0开始计算的,因此真实天数需要在此基础上加1。

php怎么替换nbsp空格符php怎么替换nbsp空格符Apr 24, 2022 pm 02:55 PM

方法:1、用“str_replace(" ","其他字符",$str)”语句,可将nbsp符替换为其他字符;2、用“preg_replace("/(\s|\&nbsp\;||\xc2\xa0)/","其他字符",$str)”语句。

php怎么查找字符串是第几位php怎么查找字符串是第几位Apr 22, 2022 pm 06:48 PM

查找方法:1、用strpos(),语法“strpos("字符串值","查找子串")+1”;2、用stripos(),语法“strpos("字符串值","查找子串")+1”。因为字符串是从0开始计数的,因此两个函数获取的位置需要进行加1处理。

See all articles

Heiße KI -Werkzeuge

Undresser.AI Undress

Undresser.AI Undress

KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover

AI Clothes Remover

Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool

Undress AI Tool

Ausziehbilder kostenlos

Clothoff.io

Clothoff.io

KI-Kleiderentferner

AI Hentai Generator

AI Hentai Generator

Erstellen Sie kostenlos Ai Hentai.

Heiße Werkzeuge

MantisBT

MantisBT

Mantis ist ein einfach zu implementierendes webbasiertes Tool zur Fehlerverfolgung, das die Fehlerverfolgung von Produkten unterstützen soll. Es erfordert PHP, MySQL und einen Webserver. Schauen Sie sich unsere Demo- und Hosting-Services an.

MinGW – Minimalistisches GNU für Windows

MinGW – Minimalistisches GNU für Windows

Dieses Projekt wird derzeit auf osdn.net/projects/mingw migriert. Sie können uns dort weiterhin folgen. MinGW: Eine native Windows-Portierung der GNU Compiler Collection (GCC), frei verteilbare Importbibliotheken und Header-Dateien zum Erstellen nativer Windows-Anwendungen, einschließlich Erweiterungen der MSVC-Laufzeit zur Unterstützung der C99-Funktionalität. Die gesamte MinGW-Software kann auf 64-Bit-Windows-Plattformen ausgeführt werden.

SublimeText3 Mac-Version

SublimeText3 Mac-Version

Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

SublimeText3 Englische Version

SublimeText3 Englische Version

Empfohlen: Win-Version, unterstützt Code-Eingabeaufforderungen!

Senden Sie Studio 13.0.1

Senden Sie Studio 13.0.1

Leistungsstarke integrierte PHP-Entwicklungsumgebung