数码资讯
PHP中INI配置原理的详细解决方案
那些使用PHP的学生知道的配置是影响遍及整个SAPI生命周期。在一个PHP脚本的执行,如果你手动修改ini配置,它将无法工作。在这一点上,如果你不能重新启动Apache和Nginx,那么你只能显式调用PHP code.ini_set的ini_set接口是一个动态的修改配置PHP提供的功能。我们需要注
选购提示
关注价格、性能、续航、售后和真实使用场景,理性比较后再下单。
那些使用PHP的学生知道的配置是影响遍及整个SAPI生命周期。在一个PHP脚本的执行,如果你手动修改ini配置,它将无法工作。在这一点上,如果你不能重新启动Apache和Nginx,那么你只能显式调用PHP code.ini_set的ini_set接口是一个动态的修改配置PHP提供的功能。我们需要注意的是,由ini_set时间配置不同于设置在INI文件配置,PHP脚本执行后,该ini_set设置将无效。
所以,本文拟分为两章,第一章的配置原则,第二将动态修改PHP配置。
对php.ini配置大致会有三条数据,configuration_hash,EG(ini_directives),和PG、BG、pcre_g,json_g,xxx_g,如果它是不明确的,这三个数据的意义是不相关的,下面将详细解释。
1,解析INI配置文件
因为php.ini需要在SAPI中生效,然后解析INI文件和基于IT构建PHP配置必须的SAPI的开始。换句话说,它必须在php.php开始需要任何实际要求配置之前已经产生到内发生。
内核,这反映在PHP,是php_module_startup功能。
php_module_startup主要负责启动PHP,即当SAPI starts.btw,另一个常见的功能是php_request_startup,这是负责每个请求在初始化的到达时间,php_module_startup和php_request_startup两标志的行动,但他们不在这个范围的分析。
例如,当挂在Apache PHP做的一个模块,然后启动Apache,所有这些模块将被激活,包括PHP模块。当PHP模块被激活,它会被称为php_module_startup.the php_module_startup功能方面做了很多工作。一旦php_module_startup通话结束,这意味着可以和PHP已经开始,现在可以接受请求和响应。
在php_module_startup功能,来解析INI文件相关的实现:
复制代码代码如下所示:
这将在php.ini设置/读取配置参数,
加载Zend扩展和登记的PHP函数的扩展
待后装。
如果(php_init_config(tsrmls_c)= =失败){
返回失败;
}
正如你所看到的,事实上,这php_init_config函数被调用来完成解析INI文件。解析工作主要从ini文件中提取关键字和值的键值lexgrammar分析和保存,php.ini的格式很简单,等号的左边是关键,而右边的是价值。哪里的PHP存储每次一双千伏是提取答案是configuration_hash,这是前面提到的。
静态hashtable configuration_hash;
的configuration_hash宣言是php_ini。C,这是一个数据结构哈希表式。顾名思义,它是一个哈希表。的方式,在不configuration_hash PHP5.3版本,因为它是一个静态的php_ini。C文件变量。后来,PHP5.3增加php_ini_get_configuration_hash接口,直接返回configuration_hash,使得PHP扩展容易看到configuration_hash全貌。
注意四点:
首先,php_init_config不除词汇语法做什么。也就是说,如果我们在INI文件中添加一个你好=世界,只要它是正确的配置项的格式,它最终将configuration_hash包含对你好的关键,对世界的元素的值,configuration_hash最大体现ini文件。
第二,ini文件允许我们以数组的形式对它进行配置。例如,下面的三行是在INI文件中编写的:
复制代码代码如下所示:
{ } = 1度漂移。
{ } = 2度漂移。
{ } = 3度漂移。
然后在最后产生的configuration_hash表,将有关键drift.arr元素,其值为三的数字1,2, 3.this数组是一种非常罕见的配置方法。
第三、PHP也让我们除了默认的php.ini文件建立一些INI文件(是PHP % s.ini)。这些文件将被放置在一个额外的目录。目录是由环境变量指定的php_ini_scan_dir。当php_init_config解析php.ini,它会扫描目录,然后找出所有INI目录中的文件进行分析。KV键值对这些额外的INI文件的产生也将添加到configuration_hash。
这是一个偶尔有用的特性。假设我们自己开发PHP扩展,但不想进入的混合配置,那么我们可以写一个ini,告诉php_ini_scan_dir哪里通过PHP找到它。当然,它的缺点也是显而易见的,他们需要额外的环境变量来支持他们。一个更好的解决方案是:开发者调用php_parse_user_ini_file或zend_parse_ini_file解析相应的ini文件的扩展名。
第四、在configuration_hash,关键是一个字符串,那么什么是值类型答案也是字符串(除了上面有一个非常特别的数组):
复制代码代码如下所示:
在display_errors =
log_errors =关闭
log_errors_max_len = 1024
那么关键值对实际存储在最后configuration_hash是:
复制代码代码如下所示:
关键词:display_errors
瓦尔:1
关键词:log_errors
瓦尔:
关键词:log_errors_max_len
瓦尔:1024
注意log_errors,其价值甚至不是另外0,log_errors_max_len不是数字,而是一个字串1024。
在这一点上,很显然INI文件的内容基本上被解析了:
1、解析INI发生在php_module_startup阶段
2、分析结果存储在configuration_hash。
2、对模块的配置功能
PHP的一般结构可看作是在底层Zend引擎。它负责与OS交互、编译PHP代码、提供内存托管等等。在Zend引擎的上层,有很多模块,其中最重要的是一个核心模块,和其他类似的标准,PCRE、日期、会议等…这些模块有另一个名称,称为PHP扩展,我们可以简单地理解,每个模块将为开发人员提供一组功能性接口,例如,标准模块提供了常用的内置函数,如爆炸、修剪、数组。
我为什么要谈这个因为在php.ini中,有相当多的配置等模块,除了PHP本身,或为核心模块,如safe_mode,display_errors,max_execution_time,等。
例如,日期模块,它提供了一个共同的作用时间、日期,strtotime,等等。在php.ini中,其相关的配置是一样的:
复制代码代码如下所示:
{日}
date.timezone =亚细亚 /上海
date.default_latitude = 31.7667
date.default_longitude = 35.2333
date.sunrise_zenith = 90.583333
date.sunset_zenith = 90.583333
除了这些模块的独立配置,Zend引擎也兼容,但Zend引擎可以分配的很少,只有error_reporting,zend.enable_gc和detect_unicode三项。
在前面的章节中,我们已经谈到了php_module_startup调用php_init_config,旨在解析INI文件并生成configuration_hash.so做什么在php_module_startup下吗很明显,configuration_hash配置将用于诸如Zend,核心,标准不同的模块,SPL等等。当然,这不是一个一蹴而就的过程,因为PHP通常包含多个模块,这些模块在PHP启动过程也开始转向。然后,配置发生在启动过程中的模块的模块的过程
扩展开发经验的学生会直接指出模块的启动是不php_minit_function(一)
是的,如果一个模块需要进行配置,然后在php_minit_function,你可以叫register_ini_entries()做it.register_ini_entries会去configuration_hash找到用户设置的配置值和更新的模块的全局空间根据当前模块所需要的配置项的名称。
2.1,模块的全局空间
了解如何配置INI配置configuration_hash各模块,有必要了解PHP模块的全局空间。不同的PHP模块,你可以打开自己的存储空间,这个空间是模块的全局可见。在一般情况下,它会被用来存储该模块所需的INI配置。换句话说,在configuration_hash配置项目最终将被存储在全局空间。在模块的执行,只有全球空间直接访问,并且用户可以对模块的设置。当然,它也经常被用来在模块执行记录的中间数据。
作为该bcmath模块为例,bcmath是一个PHP模块,提供了一种数学计算界面。首先,让我们看看它有什么INI配置:
复制代码代码如下所示:
php_ini_begin()
std_php_ini_entry(bcmath。规模
php_ini_end()
bcmath只有一个配置项,我们可以在php.ini bcmath.scale bcmath模块配置。
下一步,将在bcmatch模块的全局空间定义一看,php_bcmath。h,作了以下声明:
复制代码代码如下所示:
zend_begin_module_globals(bcmath)
bc_num _zero_;
bc_num _one_;
bc_num _two_;
长bc_precision;
zend_end_module_globals(bcmath)
宏观扩张之后,那就是:
复制代码代码如下所示:
_zend_bcmath_globals { typedef struct
bc_num _zero_;
bc_num _one_;
bc_num _two_;
长bc_precision;
zend_bcmath_globals };
事实上,这zend_bcmath_globals类型在bcmath模块的全局空间类型。在这里,只有zend_bcmath_globals结构声明,并有一个具体的实例定义bcmath C:
该zend_bcmath_globals bcmath_globals / 开始后/;
zend_declare_module_globals(bcmath)
你可以看到,变量的定义是通过zend_declare_module_globals bcmath_globals。
bcmath_globals是一个真正的全球空间,其中包含四场。最后一场,bc_precision,对应的INI配置bcmath.scale。我们在bcmath.scale php.ini的价值。然后,当我们开始bcmath模块,对bcmath.scale的值更新为bcmath_globals.bc_precision。
更新值的变量configuration_hash xxx_globals每个模块本身的定义,也就是所谓的INI配置角色模块。一旦模块启动,这些配置也很到位。所以,在随后的执行阶段,PHP模块不需要访问configuration_hash再次,模块只需要访问自己的xxx_globals,它可以让用户配置。
bcmath_globals,除了有一场对INI配置项,其他三个字段的含义是什么这是模块全局空间的第二个角色,它除了ini配置之外,还可以在模块执行过程中存储一些数据。
例如,JSON模块也是PHP中非常常见的模块:
复制代码代码如下所示:
zend_begin_module_globals(JSON)
国际error_code;
zend_end_module_globals(JSON)
你可以看到,JSON模块不需要一个ini配置,它已经在其全球space.error_code只有一场error_code记录在json_decode或json_encode.the json_last_error函数之前执行发生的错误返回error_code帮助用户定位错误的原因。
为了能够方便地访问该模块的全局变量的空间,PHP已经提出了一些宏。例如,如果我们想访问error_code在json_globals,我们可以写json_globals.error_code直接,但是写的更一般的方法是json_g宏定义。
复制代码代码如下所示:
#定义json_g(V)(json_globals。V)
我们用json_g(error_code)访问json_globals.error_code.at本文开头,我们提到了PG、BG、json_g,pcre_g,xxx_g等等,这在PHP源代码也很常见。现在我们可以理解他们很容易。PG宏可以访问核心模块的全局变量,标准模块的BG访问全局变量和pcre_g然后访问PCRE模块的全局变量。
复制代码代码如下所示:
#定义PG(V)(core_globals。V)
#定义BG(V)(basic_globals。V)
2.2,如何确定模块需要什么配置
模块需要什么样的INI配置,这是在每个模块本身中定义的,例如,对于核心模块,有如下的配置定义:
复制代码代码如下所示:
php_ini_begin()
......
std_php_ini_entry_ex(display_errors
std_php_ini_boolean(enable_dl
std_php_ini_boolean(expose_php
std_php_ini_boolean(safe_mode
......
php_ini_end()
上面的代码中可以找到PHP src 主主。C文件约450。其中,有更多的宏,如zend_ini_begin,zend_ini_end,php_ini_entry_ex,std_php_ini_boolean等等。
上面的代码是通过宏扩展来执行的。
复制代码代码如下所示:
静态常量zend_ini_entry ini_entries { } = { {
。
{ 0,php_ini_all display_errors ,
{ 0,php_ini_system enable_dl ,
{ 0,php_ini_system expose_php ,
{ 0,php_ini_system safe_mode ,
…
{ 0, 0,空,0,空,空,空,空,空,0,空,0, 0, 0,空}
};
我们看到,一个配置项的定义实质上是对zend_ini_entry类型数组的定义。对zend_ini_entry结构领域的具体含义是:
复制代码代码如下所示:
结构_zend_ini_entry {
国际module_number; / / ID模块
int修改; / /范围可以被修改,如php.ini,ini_set
名称;配置项的名称。
单位name_length;
zend_ini_mh((* on_modify)); / /回调函数,当调用注册或修改的配置项
void * mh_arg1; / /通常配置在xxx_g字段偏移量
void * mh_arg2; / /通常是xxx_g
void * mh_arg3; / /通常保留字段,很少使用
char *值;配置值
单位value_length;
char * orig_value; / /配置项的初始值。
单位orig_value_length;
国际orig_modifiable;对原始的修改 / /配置
int修饰; / /任何变化,如果有变化,orig_value将保存的值之前
void(*显示器)(zend_ini_entry * ini_entry,int类型);
};
2.3、配置作为一个模块,register_ini_entries
register_ini_entries经常可以看到不同的扩展php_minit_function.register_ini_entries主要负责两件事。首先,填写模块的全局空间xxx_g和configuration_hash到xxx_g.second价值同步,也会产生如(ini_directives)。
register_ini_entries也是一个宏,并展开后,它实际上是一个zend_register_ini_entries方法,zend_register_ini_entries实施具体。
复制代码代码如下所示:
zend_api(const int zend_register_ini_entries zend_ini_entry * ini_entry,int module_number tsrmls_dc) / / *
{
/ / ini_entry型zend_ini_entry数组,每个数组指针p
const zend_ini_entry×P = ini_entry;
zend_ini_entry * hashed_ini_entry;
default_value zval;
/ /乙二醇(ini_directives)是registered_zend_ini_directives
哈希表*指令= registered_zend_ini_directives;
zend_bool config_directive_success = 0;
记得ini_entry / /最后固定{ 0, 0,null,…}。
当(p >名称){
config_directive_success = 0;
P对zend_ini_entry / /添加EG(ini_directives)
如果(zend_hash_add(指令、P ->名称-> name_length,P,P(void *),sizeof(zend_ini_entry),(void)hashed_ini_entry)= =失败){
zend_unregister_ini_entries(module_number tsrmls_cc);
返回失败;
}
hashed_ini_entry -> module_number = module_number;
据configuration_hash名称 / /查询,把结果default_value
/ /注意default_value值一般是比较原始的,数字、字符串和数组,根据不同的风格
如果((zend_get_configuration_directive(P >的名字,P>name_length,default_value))= =成功){
/ /电话on_modify更新全球空间中的xxx_g模块
如果(hashed_ini_entry -> on_modify | |!hashed_ini_entry -> on_modify(hashed_ini_entry,z_strval(default_value),z_strlen(default_value),hashed_ini_entry -> mh_arg1,hashed_ini_entry -> mh_arg2,hashed_ini_entry -> mh_arg3,zend_ini_stage_startup,tsrmls_cc)= =成功){
hashed_ini_entry ->价值= z_strval(default_value);
hashed_ini_entry -> value_length = z_strlen(default_value);
config_directive_success = 1;
}
}
/ /如果configuration_hash没有找到,使用默认值
如果(!config_directive_success hashed_ini_entry -> on_modify){
hashed_ini_entry -> on_modify(hashed_ini_entry,hashed_ini_entry ->价值,hashed_ini_entry -> value_length,hashed_ini_entry -> mh_arg1,hashed_ini_entry -> mh_arg2,hashed_ini_entry -> mh_arg3,zend_ini_stage_startup tsrmls_cc)。
}
++;
}
返回成功;
}
简言之,上述代码的逻辑可以表示为:
1、添加ini配置项的模块声明如(ini_directives)。注意,INI配置项的值可以修改。
2,试着去configuration_hash找到每个模块所需的INI。
如果可以找到,用户在值的INI文件中配置,然后用户配置。
如果你找不到它,没关系,因为当它声明ini时,模块将接受默认值。
3、同步INI值为xx_g.after,在PHP的执行,这是xxx_globals.the具体过程是调用on_modify方法对应的INI配置,和on_modify是由指定的模块时,它声明INI。
让我们on_modify一看,这实际上是一个函数指针看两个核心模块的配置声明:
复制代码代码如下所示:
std_php_ini_boolean(log_errors
std_php_ini_entry(log_errors_max_len
对于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;
说的core_globals地址 / /基地
char *基=(char *)mh_arg2;
说的core_globals / / P加log_errors地址字段偏移
让 / /是log_errors地址字段
P =(zend_bool *)(基地+(size_t)mh_arg1);
如果(new_value_length = = 2 strcasecmp(,new_value)= = 0){
* P =(zend_bool)1;
}
如果(new_value_length = = 3 strcasecmp(是的,new_value)= = 0){
* P =(zend_bool)1;
}
如果(new_value_length = = 4 strcasecmp(真的,new_value)= = 0){
* P =(zend_bool)1;
}
{其他
价值/ configuration_hash存储为字符串1
所以这里 / / atoi为数1
* P =(zend_bool)atoi(new_value);
}
返回成功;
}
最令人费解的是mh_arg1和mh_arg2,估计事实上,控制zend_ini_entry,定义的mh_arg1,mh_arg2是understand.mh_arg1很容易表示的字节偏移量,和mh_arg2代表的xxx_globals.therefore地址,结果(char *)mh_arg2 + mh_arg1在xxx_globals.specifically字段的地址,在这种情况下,它是在core_globals.so的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)
{
长*;
char *基=(char *)mh_arg2;
得到地址 / / log_errors_max_len
P =(长*)(基地+(size_t)mh_arg1);
1024 / /成长型,并分配给core_globals.log_errors_max_len
* P = zend_atol(new_value,new_value_length);
返回成功;
}
最后,需要注意的是,如果在zend_register_ini_entries功能configuration_hash功能配置的重要价值,当完成后,在hashed_ini_entry价值和value_length将被更新,如果用户已配置php.ini,然后如(ini_directives)存储在实际配置价值。如果用户不匹配,EG(ini_directives)存储在默认值时,zend_ini_entry声明。
在zend_register_ini_entries default_value变量的命名是不好的,很容易误解。事实上,default_value不是缺省值,但用户实际配置价值。
3、总结
在这一点上,三个数据configuration_hash,EG(ini_directives),和PG、BG、pcre_g,json_g,xxx_g已明确。
总结:
1、configuration_hash,存储配置php.ini文件,不做检查,其值是一个字符串。
2、如(ini_directives)在每个模块中定义的zend_ini_entry店。如果用户配置php.ini(configuration_hash存在),该值是通过configuration_hash价值所取代,而仍然是一个字符串类型。
3、xxx_g,用来访问该模块的全局空间。这个内存空间可以用来存储INI配置和更新,通过指定的on_modify功能,其数据类型是由xxx_g字段声明的确定。
所以,本文拟分为两章,第一章的配置原则,第二将动态修改PHP配置。
对php.ini配置大致会有三条数据,configuration_hash,EG(ini_directives),和PG、BG、pcre_g,json_g,xxx_g,如果它是不明确的,这三个数据的意义是不相关的,下面将详细解释。
1,解析INI配置文件
因为php.ini需要在SAPI中生效,然后解析INI文件和基于IT构建PHP配置必须的SAPI的开始。换句话说,它必须在php.php开始需要任何实际要求配置之前已经产生到内发生。
内核,这反映在PHP,是php_module_startup功能。
php_module_startup主要负责启动PHP,即当SAPI starts.btw,另一个常见的功能是php_request_startup,这是负责每个请求在初始化的到达时间,php_module_startup和php_request_startup两标志的行动,但他们不在这个范围的分析。
例如,当挂在Apache PHP做的一个模块,然后启动Apache,所有这些模块将被激活,包括PHP模块。当PHP模块被激活,它会被称为php_module_startup.the php_module_startup功能方面做了很多工作。一旦php_module_startup通话结束,这意味着可以和PHP已经开始,现在可以接受请求和响应。
在php_module_startup功能,来解析INI文件相关的实现:
复制代码代码如下所示:
这将在php.ini设置/读取配置参数,
加载Zend扩展和登记的PHP函数的扩展
待后装。
如果(php_init_config(tsrmls_c)= =失败){
返回失败;
}
正如你所看到的,事实上,这php_init_config函数被调用来完成解析INI文件。解析工作主要从ini文件中提取关键字和值的键值lexgrammar分析和保存,php.ini的格式很简单,等号的左边是关键,而右边的是价值。哪里的PHP存储每次一双千伏是提取答案是configuration_hash,这是前面提到的。
静态hashtable configuration_hash;
的configuration_hash宣言是php_ini。C,这是一个数据结构哈希表式。顾名思义,它是一个哈希表。的方式,在不configuration_hash PHP5.3版本,因为它是一个静态的php_ini。C文件变量。后来,PHP5.3增加php_ini_get_configuration_hash接口,直接返回configuration_hash,使得PHP扩展容易看到configuration_hash全貌。
注意四点:
首先,php_init_config不除词汇语法做什么。也就是说,如果我们在INI文件中添加一个你好=世界,只要它是正确的配置项的格式,它最终将configuration_hash包含对你好的关键,对世界的元素的值,configuration_hash最大体现ini文件。
第二,ini文件允许我们以数组的形式对它进行配置。例如,下面的三行是在INI文件中编写的:
复制代码代码如下所示:
{ } = 1度漂移。
{ } = 2度漂移。
{ } = 3度漂移。
然后在最后产生的configuration_hash表,将有关键drift.arr元素,其值为三的数字1,2, 3.this数组是一种非常罕见的配置方法。
第三、PHP也让我们除了默认的php.ini文件建立一些INI文件(是PHP % s.ini)。这些文件将被放置在一个额外的目录。目录是由环境变量指定的php_ini_scan_dir。当php_init_config解析php.ini,它会扫描目录,然后找出所有INI目录中的文件进行分析。KV键值对这些额外的INI文件的产生也将添加到configuration_hash。
这是一个偶尔有用的特性。假设我们自己开发PHP扩展,但不想进入的混合配置,那么我们可以写一个ini,告诉php_ini_scan_dir哪里通过PHP找到它。当然,它的缺点也是显而易见的,他们需要额外的环境变量来支持他们。一个更好的解决方案是:开发者调用php_parse_user_ini_file或zend_parse_ini_file解析相应的ini文件的扩展名。
第四、在configuration_hash,关键是一个字符串,那么什么是值类型答案也是字符串(除了上面有一个非常特别的数组):
复制代码代码如下所示:
在display_errors =
log_errors =关闭
log_errors_max_len = 1024
那么关键值对实际存储在最后configuration_hash是:
复制代码代码如下所示:
关键词:display_errors
瓦尔:1
关键词:log_errors
瓦尔:
关键词:log_errors_max_len
瓦尔:1024
注意log_errors,其价值甚至不是另外0,log_errors_max_len不是数字,而是一个字串1024。
在这一点上,很显然INI文件的内容基本上被解析了:
1、解析INI发生在php_module_startup阶段
2、分析结果存储在configuration_hash。
2、对模块的配置功能
PHP的一般结构可看作是在底层Zend引擎。它负责与OS交互、编译PHP代码、提供内存托管等等。在Zend引擎的上层,有很多模块,其中最重要的是一个核心模块,和其他类似的标准,PCRE、日期、会议等…这些模块有另一个名称,称为PHP扩展,我们可以简单地理解,每个模块将为开发人员提供一组功能性接口,例如,标准模块提供了常用的内置函数,如爆炸、修剪、数组。
我为什么要谈这个因为在php.ini中,有相当多的配置等模块,除了PHP本身,或为核心模块,如safe_mode,display_errors,max_execution_time,等。
例如,日期模块,它提供了一个共同的作用时间、日期,strtotime,等等。在php.ini中,其相关的配置是一样的:
复制代码代码如下所示:
{日}
date.timezone =亚细亚 /上海
date.default_latitude = 31.7667
date.default_longitude = 35.2333
date.sunrise_zenith = 90.583333
date.sunset_zenith = 90.583333
除了这些模块的独立配置,Zend引擎也兼容,但Zend引擎可以分配的很少,只有error_reporting,zend.enable_gc和detect_unicode三项。
在前面的章节中,我们已经谈到了php_module_startup调用php_init_config,旨在解析INI文件并生成configuration_hash.so做什么在php_module_startup下吗很明显,configuration_hash配置将用于诸如Zend,核心,标准不同的模块,SPL等等。当然,这不是一个一蹴而就的过程,因为PHP通常包含多个模块,这些模块在PHP启动过程也开始转向。然后,配置发生在启动过程中的模块的模块的过程
扩展开发经验的学生会直接指出模块的启动是不php_minit_function(一)
是的,如果一个模块需要进行配置,然后在php_minit_function,你可以叫register_ini_entries()做it.register_ini_entries会去configuration_hash找到用户设置的配置值和更新的模块的全局空间根据当前模块所需要的配置项的名称。
2.1,模块的全局空间
了解如何配置INI配置configuration_hash各模块,有必要了解PHP模块的全局空间。不同的PHP模块,你可以打开自己的存储空间,这个空间是模块的全局可见。在一般情况下,它会被用来存储该模块所需的INI配置。换句话说,在configuration_hash配置项目最终将被存储在全局空间。在模块的执行,只有全球空间直接访问,并且用户可以对模块的设置。当然,它也经常被用来在模块执行记录的中间数据。
作为该bcmath模块为例,bcmath是一个PHP模块,提供了一种数学计算界面。首先,让我们看看它有什么INI配置:
复制代码代码如下所示:
php_ini_begin()
std_php_ini_entry(bcmath。规模
php_ini_end()
bcmath只有一个配置项,我们可以在php.ini bcmath.scale bcmath模块配置。
下一步,将在bcmatch模块的全局空间定义一看,php_bcmath。h,作了以下声明:
复制代码代码如下所示:
zend_begin_module_globals(bcmath)
bc_num _zero_;
bc_num _one_;
bc_num _two_;
长bc_precision;
zend_end_module_globals(bcmath)
宏观扩张之后,那就是:
复制代码代码如下所示:
_zend_bcmath_globals { typedef struct
bc_num _zero_;
bc_num _one_;
bc_num _two_;
长bc_precision;
zend_bcmath_globals };
事实上,这zend_bcmath_globals类型在bcmath模块的全局空间类型。在这里,只有zend_bcmath_globals结构声明,并有一个具体的实例定义bcmath C:
该zend_bcmath_globals bcmath_globals / 开始后/;
zend_declare_module_globals(bcmath)
你可以看到,变量的定义是通过zend_declare_module_globals bcmath_globals。
bcmath_globals是一个真正的全球空间,其中包含四场。最后一场,bc_precision,对应的INI配置bcmath.scale。我们在bcmath.scale php.ini的价值。然后,当我们开始bcmath模块,对bcmath.scale的值更新为bcmath_globals.bc_precision。
更新值的变量configuration_hash xxx_globals每个模块本身的定义,也就是所谓的INI配置角色模块。一旦模块启动,这些配置也很到位。所以,在随后的执行阶段,PHP模块不需要访问configuration_hash再次,模块只需要访问自己的xxx_globals,它可以让用户配置。
bcmath_globals,除了有一场对INI配置项,其他三个字段的含义是什么这是模块全局空间的第二个角色,它除了ini配置之外,还可以在模块执行过程中存储一些数据。
例如,JSON模块也是PHP中非常常见的模块:
复制代码代码如下所示:
zend_begin_module_globals(JSON)
国际error_code;
zend_end_module_globals(JSON)
你可以看到,JSON模块不需要一个ini配置,它已经在其全球space.error_code只有一场error_code记录在json_decode或json_encode.the json_last_error函数之前执行发生的错误返回error_code帮助用户定位错误的原因。
为了能够方便地访问该模块的全局变量的空间,PHP已经提出了一些宏。例如,如果我们想访问error_code在json_globals,我们可以写json_globals.error_code直接,但是写的更一般的方法是json_g宏定义。
复制代码代码如下所示:
#定义json_g(V)(json_globals。V)
我们用json_g(error_code)访问json_globals.error_code.at本文开头,我们提到了PG、BG、json_g,pcre_g,xxx_g等等,这在PHP源代码也很常见。现在我们可以理解他们很容易。PG宏可以访问核心模块的全局变量,标准模块的BG访问全局变量和pcre_g然后访问PCRE模块的全局变量。
复制代码代码如下所示:
#定义PG(V)(core_globals。V)
#定义BG(V)(basic_globals。V)
2.2,如何确定模块需要什么配置
模块需要什么样的INI配置,这是在每个模块本身中定义的,例如,对于核心模块,有如下的配置定义:
复制代码代码如下所示:
php_ini_begin()
......
std_php_ini_entry_ex(display_errors
std_php_ini_boolean(enable_dl
std_php_ini_boolean(expose_php
std_php_ini_boolean(safe_mode
......
php_ini_end()
上面的代码中可以找到PHP src 主主。C文件约450。其中,有更多的宏,如zend_ini_begin,zend_ini_end,php_ini_entry_ex,std_php_ini_boolean等等。
上面的代码是通过宏扩展来执行的。
复制代码代码如下所示:
静态常量zend_ini_entry ini_entries { } = { {
。
{ 0,php_ini_all display_errors ,
{ 0,php_ini_system enable_dl ,
{ 0,php_ini_system expose_php ,
{ 0,php_ini_system safe_mode ,
…
{ 0, 0,空,0,空,空,空,空,空,0,空,0, 0, 0,空}
};
我们看到,一个配置项的定义实质上是对zend_ini_entry类型数组的定义。对zend_ini_entry结构领域的具体含义是:
复制代码代码如下所示:
结构_zend_ini_entry {
国际module_number; / / ID模块
int修改; / /范围可以被修改,如php.ini,ini_set
名称;配置项的名称。
单位name_length;
zend_ini_mh((* on_modify)); / /回调函数,当调用注册或修改的配置项
void * mh_arg1; / /通常配置在xxx_g字段偏移量
void * mh_arg2; / /通常是xxx_g
void * mh_arg3; / /通常保留字段,很少使用
char *值;配置值
单位value_length;
char * orig_value; / /配置项的初始值。
单位orig_value_length;
国际orig_modifiable;对原始的修改 / /配置
int修饰; / /任何变化,如果有变化,orig_value将保存的值之前
void(*显示器)(zend_ini_entry * ini_entry,int类型);
};
2.3、配置作为一个模块,register_ini_entries
register_ini_entries经常可以看到不同的扩展php_minit_function.register_ini_entries主要负责两件事。首先,填写模块的全局空间xxx_g和configuration_hash到xxx_g.second价值同步,也会产生如(ini_directives)。
register_ini_entries也是一个宏,并展开后,它实际上是一个zend_register_ini_entries方法,zend_register_ini_entries实施具体。
复制代码代码如下所示:
zend_api(const int zend_register_ini_entries zend_ini_entry * ini_entry,int module_number tsrmls_dc) / / *
{
/ / ini_entry型zend_ini_entry数组,每个数组指针p
const zend_ini_entry×P = ini_entry;
zend_ini_entry * hashed_ini_entry;
default_value zval;
/ /乙二醇(ini_directives)是registered_zend_ini_directives
哈希表*指令= registered_zend_ini_directives;
zend_bool config_directive_success = 0;
记得ini_entry / /最后固定{ 0, 0,null,…}。
当(p >名称){
config_directive_success = 0;
P对zend_ini_entry / /添加EG(ini_directives)
如果(zend_hash_add(指令、P ->名称-> name_length,P,P(void *),sizeof(zend_ini_entry),(void)hashed_ini_entry)= =失败){
zend_unregister_ini_entries(module_number tsrmls_cc);
返回失败;
}
hashed_ini_entry -> module_number = module_number;
据configuration_hash名称 / /查询,把结果default_value
/ /注意default_value值一般是比较原始的,数字、字符串和数组,根据不同的风格
如果((zend_get_configuration_directive(P >的名字,P>name_length,default_value))= =成功){
/ /电话on_modify更新全球空间中的xxx_g模块
如果(hashed_ini_entry -> on_modify | |!hashed_ini_entry -> on_modify(hashed_ini_entry,z_strval(default_value),z_strlen(default_value),hashed_ini_entry -> mh_arg1,hashed_ini_entry -> mh_arg2,hashed_ini_entry -> mh_arg3,zend_ini_stage_startup,tsrmls_cc)= =成功){
hashed_ini_entry ->价值= z_strval(default_value);
hashed_ini_entry -> value_length = z_strlen(default_value);
config_directive_success = 1;
}
}
/ /如果configuration_hash没有找到,使用默认值
如果(!config_directive_success hashed_ini_entry -> on_modify){
hashed_ini_entry -> on_modify(hashed_ini_entry,hashed_ini_entry ->价值,hashed_ini_entry -> value_length,hashed_ini_entry -> mh_arg1,hashed_ini_entry -> mh_arg2,hashed_ini_entry -> mh_arg3,zend_ini_stage_startup tsrmls_cc)。
}
++;
}
返回成功;
}
简言之,上述代码的逻辑可以表示为:
1、添加ini配置项的模块声明如(ini_directives)。注意,INI配置项的值可以修改。
2,试着去configuration_hash找到每个模块所需的INI。
如果可以找到,用户在值的INI文件中配置,然后用户配置。
如果你找不到它,没关系,因为当它声明ini时,模块将接受默认值。
3、同步INI值为xx_g.after,在PHP的执行,这是xxx_globals.the具体过程是调用on_modify方法对应的INI配置,和on_modify是由指定的模块时,它声明INI。
让我们on_modify一看,这实际上是一个函数指针看两个核心模块的配置声明:
复制代码代码如下所示:
std_php_ini_boolean(log_errors
std_php_ini_entry(log_errors_max_len
对于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;
说的core_globals地址 / /基地
char *基=(char *)mh_arg2;
说的core_globals / / P加log_errors地址字段偏移
让 / /是log_errors地址字段
P =(zend_bool *)(基地+(size_t)mh_arg1);
如果(new_value_length = = 2 strcasecmp(,new_value)= = 0){
* P =(zend_bool)1;
}
如果(new_value_length = = 3 strcasecmp(是的,new_value)= = 0){
* P =(zend_bool)1;
}
如果(new_value_length = = 4 strcasecmp(真的,new_value)= = 0){
* P =(zend_bool)1;
}
{其他
价值/ configuration_hash存储为字符串1
所以这里 / / atoi为数1
* P =(zend_bool)atoi(new_value);
}
返回成功;
}
最令人费解的是mh_arg1和mh_arg2,估计事实上,控制zend_ini_entry,定义的mh_arg1,mh_arg2是understand.mh_arg1很容易表示的字节偏移量,和mh_arg2代表的xxx_globals.therefore地址,结果(char *)mh_arg2 + mh_arg1在xxx_globals.specifically字段的地址,在这种情况下,它是在core_globals.so的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)
{
长*;
char *基=(char *)mh_arg2;
得到地址 / / log_errors_max_len
P =(长*)(基地+(size_t)mh_arg1);
1024 / /成长型,并分配给core_globals.log_errors_max_len
* P = zend_atol(new_value,new_value_length);
返回成功;
}
最后,需要注意的是,如果在zend_register_ini_entries功能configuration_hash功能配置的重要价值,当完成后,在hashed_ini_entry价值和value_length将被更新,如果用户已配置php.ini,然后如(ini_directives)存储在实际配置价值。如果用户不匹配,EG(ini_directives)存储在默认值时,zend_ini_entry声明。
在zend_register_ini_entries default_value变量的命名是不好的,很容易误解。事实上,default_value不是缺省值,但用户实际配置价值。
3、总结
在这一点上,三个数据configuration_hash,EG(ini_directives),和PG、BG、pcre_g,json_g,xxx_g已明确。
总结:
1、configuration_hash,存储配置php.ini文件,不做检查,其值是一个字符串。
2、如(ini_directives)在每个模块中定义的zend_ini_entry店。如果用户配置php.ini(configuration_hash存在),该值是通过configuration_hash价值所取代,而仍然是一个字符串类型。
3、xxx_g,用来访问该模块的全局空间。这个内存空间可以用来存储INI配置和更新,通过指定的on_modify功能,其数据类型是由xxx_g字段声明的确定。
声明:本文内容用于数码产品信息整理与选购参考,具体价格、库存、售后政策以官方渠道和电商页面实时信息为准。