Maison > php教程 > php手册 > Explication détaillée du principe de configuration ini dans les bases de php_php

Explication détaillée du principe de configuration ini dans les bases de php_php

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
Libérer: 2016-05-16 08:59:57
original
2243 Les gens l'ont consulté

Les étudiants qui utilisent PHP savent que la configuration de php.ini prendra effet tout au long du cycle de vie de SAPI. Lors de l'exécution d'un script php, si vous modifiez manuellement la configuration ini, cela ne prendra pas effet. Si vous ne pouvez pas redémarrer Apache ou Nginx pour le moment, vous ne pouvez appeler explicitement l'interface ini_set que dans le code php. ini_set est une fonction fournie par PHP pour modifier dynamiquement la configuration. Il convient de noter que la configuration définie par ini_set et la configuration définie dans le fichier ini ont des plages de temps effectives différentes. Une fois le script php exécuté, les paramètres ini_set deviendront immédiatement invalides.

Cet article est donc divisé en deux parties. La première partie explique le principe de la configuration de php.ini, et la deuxième partie parle de la modification dynamique de la configuration de php.

La configuration de php.ini impliquera environ trois éléments de données, configuration_hash, EG (ini_directives) et PG, BG, PCRE_G, JSON_G, XXX_G, etc. Peu importe si vous ne connaissez pas la signification de ces trois types de données, elles seront expliquées en détail ci-dessous.

1, analyser le fichier de configuration INI

Puisque php.ini doit être en vigueur pendant le processus SAPI, le travail d'analyse du fichier ini et de construction de la configuration php en conséquence doit être le début de SAPI. En d’autres termes, cela doit se produire lors du processus de démarrage de PHP. PHP a besoin que ces configurations soient générées en interne avant l'arrivée de toute demande réelle.

Reflété dans le cœur de php, qui est la fonction php_module_startup.

php_module_startup est principalement responsable du démarrage de php. Il est généralement appelé au démarrage de SAPI. d'ailleurs, une autre fonction courante est php_request_startup, qui est responsable de l'initialisation de chaque requête lorsqu'elle arrive. php_module_startup et php_request_startup sont deux actions emblématiques, mais leur analyse dépasse le cadre de cet article.

Par exemple, lorsque php est connecté à un module sous Apache, alors au démarrage d'Apache, tous ces modules seront activés, y compris le module php. Lors de l'activation du module php, php_module_startup sera appelé. La fonction php_module_startup effectue beaucoup de travail. Une fois l'appel php_module_startup terminé, cela signifie, OK, php a été démarré et peut maintenant accepter les demandes et répondre.

Dans la fonction php_module_startup, l'implémentation liée à l'analyse du fichier ini est :

Copier le code Le code est le suivant :

/* ceci sera lu dans php.ini, configurera les paramètres de configuration,
Chargez les extensions zend et enregistrez les extensions de fonction php
à charger plus tard */
if (php_init_config(TSRMLS_C) == ÉCHEC) {
Retour ÉCHEC ;
>

Comme vous pouvez le voir, la fonction php_init_config est en fait appelée pour terminer l'analyse du fichier ini. Le travail d'analyse effectue principalement une analyse lexicale et grammaticale, et extrait et enregistre les paires clé et valeur dans le fichier ini. Le format de php.ini est très simple, avec la clé à gauche du signe égal et la valeur à droite. Chaque fois qu'une paire de kv est extraite, où php les stocke-t-il ? La réponse est le configuration_hash mentionné précédemment.

configuration_hash statique de la table de hachage ;
configuration_hash est déclaré dans php_ini.c, qui est une structure de données de type HashTable. Comme son nom l’indique, il s’agit en fait d’une table de hachage. En passant, configuration_hash ne peut pas être obtenu dans les versions antérieures à php5.3 car il s'agit d'une variable statique dans le fichier php_ini.c. Plus tard, php5.3 a ajouté l'interface php_ini_get_configuration_hash, qui renvoie directement &configuration_hash, afin que diverses extensions PHP puissent facilement avoir un aperçu de configuration_hash... Quelle grande bénédiction...

Notez quatre points :

Premièrement, php_init_config n'effectuera aucune vérification autre que lexicale et syntaxique. En d'autres termes, si nous ajoutons une ligne hello=world au fichier ini, tant qu'il s'agit d'un élément de configuration correctement formaté, alors le configuration_hash final contiendra un élément avec la clé hello et la valeur world, et le configuration_hash reflétera dans la mesure maximale du fichier ini.

Deuxièmement, le fichier ini nous permet de configurer sous la forme d'un tableau. Par exemple, écrivez les trois lignes suivantes dans le fichier ini :

Copier le code Le code est le suivant :

dérive.arr[]=1
dérive.arr[]=2
dérive.arr[]=3

Ensuite, dans la table configuration_hash générée finale, il y aura un élément avec la clé drift.arr, et sa valeur est un tableau contenant trois nombres : 1, 2 et 3. Il s'agit d'une méthode de configuration extrêmement rare.

Troisièmement, php nous permet également de créer des fichiers ini supplémentaires en plus du fichier php.ini par défaut (php-%s.ini pour être précis). Ces fichiers ini seront placés dans un répertoire supplémentaire. Ce répertoire est spécifié par la variable d'environnement PHP_INI_SCAN_DIR. Après que php_init_config ait analysé php.ini, il analysera à nouveau ce répertoire et trouvera tous les fichiers .ini du répertoire pour analyse. Les paires clé-valeur kv générées dans ces fichiers ini supplémentaires seront également ajoutées au configuration_hash.

C'est une fonctionnalité parfois utile. Si nous développons nous-mêmes une extension PHP mais que nous ne voulons pas mélanger la configuration dans php.ini, nous pouvons écrire une autre ini et indiquer à PHP où la trouver via PHP_INI_SCAN_DIR. Bien entendu, ses inconvénients sont également évidents et nécessitent la définition de variables d’environnement supplémentaires pour le prendre en charge. Une meilleure solution consiste pour les développeurs à appeler eux-mêmes php_parse_user_ini_file ou zend_parse_ini_file dans l'extension pour analyser le fichier ini correspondant.

Quatrièmement, dans configuration_hash, la clé est une chaîne, alors quel est le type de la valeur ? La réponse est également une chaîne (sauf pour le tableau très spécial mentionné ci-dessus). Plus précisément, comme la configuration suivante :

Copier le code Le code est le suivant :

display_errors = Activé
log_errors = Désactivé
log_errors_max_len = 1024

Ensuite, la paire clé-valeur réellement stockée dans le configuration_hash final est :

Copier le code Le code est le suivant :

clé : "display_errors"
val : "1"

clé : "log_errors"
val : ""

clé : "log_errors_max_len"
val : "1024"

Faites attention à log_errors, la valeur qu'il stocke n'est même pas "0", c'est une vraie chaîne vide. De plus, log_errors_max_len n'est pas un nombre, mais une chaîne de 1024.

À ce stade de l'analyse, pratiquement tout ce qui concerne l'analyse du fichier ini a été clairement expliqué. Pour résumer brièvement :

1, l'analyse de ini se produit à l'étape php_module_startup

2. Les résultats de l'analyse sont stockés dans configuration_hash.

2, la configuration s'applique au module

La structure générale de PHP peut être vue comme un moteur zend en bas, qui est responsable de l'interaction avec le système d'exploitation, de la compilation du code PHP, de l'hébergement de la mémoire, etc. Sur la couche supérieure du moteur zend, il existe de nombreux modules disposés. Le module principal est le module Core, et d'autres incluent Standard, PCRE, Date, Session, etc... Ces modules ont également un autre nom appelé extension php. Nous pouvons simplement comprendre que chaque module fournit un ensemble d'interfaces fonctionnelles que les développeurs peuvent appeler. Par exemple, les fonctions intégrées couramment utilisées telles que l'éclatement, le découpage, le tableau, etc. sont fournies par le module Standard.

La raison pour laquelle nous devons en parler est que dans php.ini, en plus de certaines configurations pour php lui-même, c'est-à-dire pour le module Core (comme safe_mode, display_errors, max_execution_time, etc.), il y a pas mal de quelques configurations pour d'autres modules différents de.

Par exemple, le module date, qui fournit des fonctions communes de date, d'heure, de strtotime et d'autres fonctions. Dans php.ini, sa configuration associée ressemble à :

Copier le code Le code est le suivant :

[Date]
;date.timezone = 'Asie/Shanghai'
;date.default_latitude = 31.7667
;date.default_longitude = 35.2333
;date.sunrise_zenith = 90.583333
;date.sunset_zenith = 90.583333

En plus de ces modules ayant des configurations indépendantes, le moteur zend est également configurable, mais le moteur zend a très peu d'éléments configurables, seulement error_reporting, zend.enable_gc et detector_unicode.

Comme nous l'avons mentionné dans la section précédente, php_module_startup appellera php_init_config, dont le but est d'analyser le fichier ini et de générer configuration_hash. Alors, que fera-t-on ensuite dans php_module_startup ? Évidemment, la configuration dans configuration_hash sera appliquée à différents modules tels que Zend, Core, Standard et SPL. Bien sûr, ce n'est pas un processus du jour au lendemain, car PHP contient généralement de nombreux modules, et ces modules seront également démarrés en séquence lors du démarrage de PHP. Ensuite, le processus de configuration du module A se produit pendant le processus de démarrage du module A.

Les étudiants ayant de l'expérience dans le développement d'extensions souligneront directement que le module A est démarré dans PHP_MINIT_FUNCTION(A), n'est-ce pas ?

Oui, si le module A doit être configuré, alors dans PHP_MINIT_FUNCTION, vous pouvez appeler REGISTER_INI_ENTRIES() pour le compléter. REGISTER_INI_ENTRIES recherchera dans configuration_hash la valeur de configuration définie par l'utilisateur en fonction du nom de l'élément de configuration requis par le module actuel et la mettra à jour dans le propre espace global du module.

2.1, espace global du module

Pour comprendre comment appliquer la configuration ini de configuration_hash à chaque module, il faut d'abord comprendre l'espace global du module php. Pour différents modules PHP, vous pouvez ouvrir votre propre espace de stockage, et cet espace est globalement visible par le module. D'une manière générale, il servira à stocker la configuration ini requise par le module. En d'autres termes, les éléments de configuration dans configuration_hash seront finalement stockés dans l'espace global. Lors de l'exécution du module, il vous suffit d'accéder directement à cet espace global pour obtenir les paramètres utilisateur du module. Bien entendu, il est aussi souvent utilisé pour enregistrer des données intermédiaires lors de l’exécution du module.

Prenons le module bcmath comme exemple. bcmath est un module php qui fournit une interface pour les calculs mathématiques. Tout d'abord, jetons un œil à sa configuration ini :

Copier le code Le code est le suivant :

PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("bcmath.scale", "0", PHP_INI_ALL, OnUpdateLongGEZero, bc_precision, zend_bcmath_globals, bcmath_globals)
PHP_INI_END()

bcmath n'a qu'un seul élément de configuration. Nous pouvons utiliser bcmath.scale dans php.ini pour configurer le module bcmath.

Ensuite, continuez à regarder la définition de l'espace global du module bcmatch. Il y a la déclaration suivante dans php_bcmath.h :

Copier le code Le code est le suivant :

ZEND_BEGIN_MODULE_GLOBALS(bcmath)
bc_num _zéro_;
bc_num _one_;
bc_num _two_;
longue bc_precision;
ZEND_END_MODULE_GLOBALS(bcmath)

Une fois la macro développée, elle est :

Copier le code Le code est le suivant :

typedef struct _zend_bcmath_globals {
bc_num _zéro_;
bc_num _one_;
bc_num _two_;
longue bc_precision;
} zend_bcmath_globals;

En fait, le type zend_bcmath_globals est le type d'espace global dans le module bcmath. Seule la structure zend_bcmath_globals est déclarée ici, et il existe une définition d'instanciation spécifique dans bcmath.c :

// Après expansion, c'est zend_bcmath_globals bcmath_globals;
ZEND_DECLARE_MODULE_GLOBALS(bcmath)
On voit que la définition de la variable bcmath_globals se complète avec ZEND_DECLARE_MODULE_GLOBALS.

bcmath_globals est un véritable espace global, qui contient quatre champs. Son dernier champ, bc_precision, correspond à bcmath.scale dans la configuration ini. Nous définissons la valeur de bcmath.scale dans php.ini, puis lors du démarrage du module bcmath, la valeur de bcmath.scale est mise à jour en bcmath_globals.bc_precision.

Mettez à jour la valeur dans configuration_hash avec la variable xxx_globals définie par chaque module, ce qu'on appelle l'application de la configuration ini au module. Une fois le module démarré, ces configurations sont en place. Par conséquent, lors de la phase d'exécution suivante, le module php n'a pas besoin d'accéder à nouveau au configuration_hash. Le module n'a besoin que d'accéder à ses propres XXX_globals pour obtenir la configuration définie par l'utilisateur.

bcmath_globals, en plus d'un champ pour l'élément de configuration ini, quels sont les trois autres champs ? C'est le deuxième rôle de l'espace global du module. En plus d'être utilisé pour la configuration ini, il peut également stocker certaines données lors de l'exécution du module.

Un autre exemple est le module json, qui est également un module très couramment utilisé en PHP :

Copier le code Le code est le suivant :

ZEND_BEGIN_MODULE_GLOBALS(json)
int error_code;
ZEND_END_MODULE_GLOBALS(json)

Vous pouvez voir que le module json ne nécessite pas de configuration ini, et son espace global n'a qu'un seul champ error_code. error_code enregistre les erreurs survenues lors de la dernière exécution de json_decode ou json_encode. La fonction json_last_error renvoie ce error_code pour aider les utilisateurs à localiser la cause de l'erreur.

Afin d'accéder facilement aux variables spatiales globales du module, PHP a classiquement proposé quelques macros. Par exemple, si nous voulons accéder au error_code dans json_globals, nous pouvons bien sûr l'écrire directement sous la forme json_globals.error_code (non disponible dans un environnement multi-thread), mais une manière plus générale de l'écrire est de définir la macro JSON_G :

Copier le code Le code est le suivant :

#define JSON_G(v) (json_globals.v)

Nous utilisons JSON_G(error_code) pour accéder à json_globals.error_code. Au début de cet article, j'ai mentionné PG, BG, JSON_G, PCRE_G, XXX_G, etc. Ces macros sont également très courantes dans le code source PHP. Nous pouvons désormais les comprendre facilement. La macro PG peut accéder aux variables globales du module Core, BG peut accéder aux variables globales du module Standard et PCRE_G peut accéder aux variables globales du module PCRE.

Copier le code Le code est le suivant :

#define PG(v) (core_globals.v)
#define BG(v) (basic_globals.v)

2.2. Comment déterminer la configuration requise par un module ?

Le type de configuration INI requis par le module est défini dans chaque module. Par exemple, pour le module Core, il existe la définition d'élément de configuration suivante :

Copier le code Le code est le suivant :

PHP_INI_BEGIN()
 …
STD_PHP_INI_ENTRY_EX("display_errors", "1", PHP_INI_ALL, OnUpdateDisplayErrors, display_errors, php_core_globals, core_globals, display_errors_mode)
STD_PHP_INI_BOOLEAN("enable_dl", "1", PHP_INI_SYSTEM, OnUpdateBool, activate_dl, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("expose_php", "1", PHP_INI_SYSTEM, OnUpdateBool, expose_php, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("safe_mode", "0", PHP_INI_SYSTEM, OnUpdateBool, safe_mode, php_core_globals, core_globals)
 …
PHP_INI_END()

Le code ci-dessus se trouve dans le fichier php-srcmainmain.c sur environ 450+ lignes. De nombreuses macros sont impliquées, notamment ZEND_INI_BEGIN, ZEND_INI_END, PHP_INI_ENTRY_EX, STD_PHP_INI_BOOLEAN, etc. Cet article n'entrera pas dans les détails une par une. Les lecteurs intéressés peuvent les analyser eux-mêmes.

Après expansion macro du code ci-dessus, nous obtenons :

Copier le code Le code est le suivant :

const statique zend_ini_entry ini_entries[] = {
..
{ 0, PHP_INI_ALL, "display_errors",sizeof("display_errors"),OnUpdateDisplayErrors,(void *)XtOffsetOf(php_core_globals, display_errors), (void *)&core_globals, NULL, "1", sizeof("1")-1, NULL, 0, 0, 0, display_errors_mode },
{ 0, PHP_INI_SYSTEM, "enable_dl", sizeof("enable_dl"), OnUpdateBool, (void *)XtOffsetOf(php_core_globals, activate_dl), (void *)&core_globals, NULL, "1", sizeof("1")-1, NULL, 0, 0, 0, zend_ini_boolean_displayer_cb },
{ 0, PHP_INI_SYSTEM, "expose_php", sizeof("expose_php"), OnUpdateBool, (void *)XtOffsetOf(php_core_globals, expose_php), (void *)&core_globals, NULL, "1", sizeof("1")-1, NULL, 0, 0, 0, zend_ini_boolean_displayer_cb },
{ 0, PHP_INI_SYSTEM, "safe_mode", sizeof("safe_mode"), OnUpdateBool, (void *)XtOffsetOf(php_core_globals, safe_mode), (void *)&core_globals, NULL, "0", sizeof("0")-1, NULL, 0, 0, 0, zend_ini_boolean_displayer_cb },
...
{ 0, 0, NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, 0, 0, 0, NULL }
};

On voit que la définition d'un élément de configuration définit essentiellement un tableau de type zend_ini_entry. La signification spécifique des champs de la structure zend_ini_entry est :

Copier le code Le code est le suivant :

struct _zend_ini_entry {
int numéro_module ; // Identifiant du module
int modifiable; // Plage pouvant être modifiée, telle que php.ini, ini_set
char *name; char *name; // Le nom de l'élément de configuration
uint nom_longueur ;
ZEND_INI_MH((*on_modify)); // Fonction de rappel, elle sera appelée lorsque l'élément de configuration est enregistré ou modifié
void *mh_arg1; // Généralement le décalage du champ de l'élément de configuration dans XXX_G
void *mh_arg2; // Généralement XXX_G
void *mh_arg3; // Généralement un champ réservé, rarement utilisé

char *value; // La valeur de l'élément de configuration
uint value_length;

char *orig_value; // La valeur originale de l'élément de configuration
uint orig_value_length;
int orig_modifiable; // Le modifiable
original de l'élément de configuration int modifié ; // Indique s'il a été modifié. S'il a été modifié, orig_value enregistrera la valeur avant la modification

.

void (*displayer)(zend_ini_entry *ini_entry, type int);
};

2.3, appliquer la configuration au module - REGISTER_INI_ENTRIES

REGISTER_INI_ENTRIES peut souvent être vu dans PHP_MINIT_FUNCTION de différentes extensions. REGISTER_INI_ENTRIES est principalement responsable de remplir deux choses : premièrement, remplir l'espace global XXX_G du module et synchroniser la valeur dans configuration_hash avec XXX_G. Deuxièmement, il génère également EG(ini_directives).

REGISTER_INI_ENTRIES est aussi une macro. Après expansion, il s'agit en fait de la méthode zend_register_ini_entries. Regardons spécifiquement l'implémentation de zend_register_ini_entries :

Copier le code Le code est le suivant :

ZEND_API int zend_register_ini_entries(const zend_ini_entry *ini_entry, int module_number TSRMLS_DC) /* {{{ */
{
// ini_entry est un tableau de type zend_ini_entry, et p est un pointeur vers chaque élément du tableau
Const zend_ini_entry *p = ini_entry;
zend_ini_entry *hashed_ini_entry;
zval default_value;
 
// EG(ini_directives) est enregistré_zend_ini_directives
HashTable *directives = enregistré_zend_ini_directives;
zend_bool config_directive_success = 0;
 
//Rappelez-vous que le dernier élément de ini_entry est fixé à {0, 0, NULL, ...}
Pendant que (p->nom) {
​​​​ config_directive_success = 0;
         
// Ajoutez le zend_ini_entry pointé par p à EG(ini_directives)
If (zend_hash_add(directives, p->name, p->name_length, (void*)p, sizeof(zend_ini_entry), (void **) &hashed_ini_entry) == FAILURE) {
              zend_unregister_ini_entries(module_number TSRMLS_CC);
              return FAILURE ;
>
           hasched_ini_entry->module_number = module_number;
         
                                // Requête dans configuration_hash en fonction du nom et place le résultat dans default_value
                          // Notez que la valeur de default_value est relativement primitive, généralement un nombre, une chaîne, un tableau, etc., selon la méthode d'écriture dans php.ini
Si ((zend_get_configuration_directive(p->name, p->name_length, &default_value)) == SUCCÈS) {
                          // Appelez on_modify pour mettre à jour vers l'espace global du module XXX_G
if (!hashed_ini_entry->on_modify || hashed_ini_entry->on_modify(hashed_ini_entry, Z_STRVAL(valeur par défaut), Z_STRLEN(valeur par défaut), hashed_ini_entry->mh_arg1, hashed_ini_entry->mh_arg2, ;mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC) = =SUCCÈS) {
                   hasched_ini_entry->value = Z_STRVAL(default_value);
                   hasched_ini_entry->value_length = Z_STRLEN(default_value);
Config_directive_success = 1 ;
            }
>

                                                                             '''         ' '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' être''''' sous à travers à travers à travers à travers à travers à travers à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à à àà à à avec avec pour avec avec avec respect Pendant    Si (!config_directive_success && hasshed_ini_entry->on_modify) {
                hashed_ini_entry->on_modify(hashed_ini_entry, hashed_ini_entry->value, hashed_ini_entry->value_length, hashed_ini_entry->mh_arg1, hashed_ini_entry->mh_arg2, > mh_arg3, ZEND_INI_STAGE_STARTUP TSRMLS_CC);
>
        p++;
>
Retour SUCCÈS ;
>

간단히 말하면 위 코드의 논리는 다음과 같이 표현할 수 있습니다.

1. 모듈에서 선언한 ini 구성 항목을 EG(ini_directives)에 추가합니다. ini 구성 항목의 값은 나중에 수정될 수 있습니다.

2.configuration_hash에서 각 모듈에 필요한 ini를 찾아보세요.

찾을 수 있다면 사용자의 ini 파일에 해당 값이 설정되어 있다는 의미이며, 사용자의 설정을 사용한다는 의미입니다.
찾을 수 없다면 문제가 되지 않습니다. 모듈이 ini를 선언할 때 기본값을 가져오기 때문입니다.
3. ini 값을 XX_G에 동기화합니다. 결국, PHP를 실행하는 동안 이러한 XXX_global은 여전히 ​​역할을 합니다. 구체적인 프로세스는 각 ini 구성에 해당하는 on_modify 메소드를 호출하는 것입니다. on_modify는 ini 선언 시 모듈에 의해 지정됩니다.

실제로 함수 포인터인 on_modify를 자세히 살펴보겠습니다. 두 가지 특정 핵심 모듈의 구성 문을 살펴보겠습니다.

코드 복사 코드는 다음과 같습니다.

STD_PHP_INI_BOOLEAN("log_errors", "0", PHP_INI_ALL, OnUpdateBool, log_errors, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("log_errors_max_len","1024", PHP_INI_ALL, OnUpdateLong, log_errors_max_len, php_core_globals, core_globals)

log_errors의 경우 on_modify는 OnUpdateBool로 설정되고, log_errors_max_len의 경우 on_modify는 OnUpdateLong으로 설정됩니다.

또한 php.ini의 구성이 다음과 같다고 가정합니다.

코드 복사 코드는 다음과 같습니다.

log_errors = 켜짐
log_errors_max_len = 1024

OnUpdateBool 함수를 자세히 살펴보겠습니다.

코드 복사 코드는 다음과 같습니다.

ZEND_API ZEND_INI_MH(OnUpdateBool)
{
zend_bool *p;
 
// base는 core_globals의 주소를 나타냅니다
char *base = (char *) mh_arg2;

// p는 core_globals의 주소와 log_errors 필드의 오프셋을 나타냅니다.
//얻은 주소는 log_errors 필드의 주소입니다
p = (zend_bool *) (base+(size_t) mh_arg1)

if (new_value_length == 2 && strcasecmp("on", new_value) == 0) {
*p = (zend_bool) 1;
}
​ else if (new_value_length == 3 && strcasecmp("yes", new_value) == 0) {
*p = (zend_bool) 1;
}
else if (new_value_length == 4 && strcasecmp("true", new_value) == 0) {
*p = (zend_bool) 1;
}
그렇지 않으면 {
​​​​ //configuration_hash에 저장된 값은 "On"이 아닌 문자열 "1"입니다
// 여기서는 atoi를 사용하여 숫자 1로 변환합니다
*p = (zend_bool) atoi(new_value);
}
성공을 반환합니다.
}

가장 당황스러운 것은 아마도 mh_arg1과 mh_arg2일 것입니다. 실제로 위에서 언급한 zend_ini_entry 정의와 비교하면 mh_arg1과 mh_arg2는 여전히 이해하기 쉽습니다. mh_arg1은 바이트 오프셋을 나타내고, mh_arg2는 XXX_globals의 주소를 나타냅니다. 따라서 (char *)mh_arg2 + mh_arg1의 결과는 XXX_globals의 필드 주소입니다. 특히 이 경우에는 core_globals에서 log_errors의 주소를 계산하는 것입니다. 따라서 OnUpdateBool이 최종적으로

로 실행되면

코드 복사 코드는 다음과 같습니다.

*p = (zend_bool) atoi(new_value);

과 기능이 동일합니다.

코드 복사 코드는 다음과 같습니다.

core_globals.log_errors = (zend_bool) atoi("1");

OnUpdateBool을 분석한 후 OnUpdateLong을 보면 한 눈에 알 수 있습니다.

코드 복사 코드는 다음과 같습니다.

ZEND_API ZEND_INI_MH(OnUpdateLong)
{
긴 *p;
char *base = (char *) mh_arg2;

// log_errors_max_len의 주소를 가져옵니다
p = (long *) (base+(size_t) mh_arg1);

// "1024"를 long 타입으로 변환하여 core_globals.log_errors_max_len에 할당
*p = zend_atol(new_value, new_value_length);
성공을 반환합니다.
}

마지막으로 주의할 점은 zend_register_ini_entries 함수에서configuration_hash에 구성이 있는 경우 on_modify가 호출될 때 hashed_ini_entry의 값과 value_length가 업데이트된다는 것입니다. 즉, 사용자가 php.ini에서 구성한 경우 EG(ini_directives)는 실제 구성된 값을 저장합니다. 사용자가 구성되지 않은 경우 EG(ini_directives)는 zend_ini_entry 선언 시 제공된 기본값을 저장합니다.

zend_register_ini_entries의 default_value 변수는 이름이 잘못되어 오해를 일으키기 쉽습니다. 실제로 default_value는 기본값을 의미하는 것이 아니라 사용자가 실제로 설정한 값을 의미합니다.

3, 요약

이제 데이터 구성_hash, EG(ini_directives) 및 PG, BG, PCRE_G, JSON_G, XXX_G...의 세 가지 부분이 모두 명확하게 설명되었습니다.

요약하자면:

1,configuration_hash는 php.ini 파일에 구성을 저장하고 검증을 수행하지 않으며 해당 값은 문자열입니다.
2. EG(ini_directives)는 각 모듈에 정의된 zend_ini_entry를 저장합니다. 사용자가 php.ini(configuration_hash에 존재)에서 구성한 경우 해당 값은configuration_hash의 값으로 대체되며 유형은 여전히 ​​문자열입니다.
3. XXX_G, 이 매크로는 모듈의 전역 공간에 액세스하는 데 사용됩니다. 이 메모리 공간은 ini 구성을 저장하고 on_modify에 지정된 함수를 통해 업데이트될 수 있습니다. 해당 데이터 유형은 XXX_G의 필드 선언에 의해 결정됩니다.

Étiquettes associées:
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers numéros
Recommandations populaires
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal