PHP函数源码之SESSION实现机制
Session是以扩展的形式嵌入到PHP内核的,所以我们可以把Session当成扩展来看待。
一般扩展被载入到PHP会经过下面几个过程
[cpp] view plain copy
- #define PHP_MINIT_FUNCTION ZEND_MODULE_STARTUP_D // 初始化module时运行
- #define PHP_MSHUTDOWN_FUNCTION ZEND_MODULE_SHUTDOWN_D // 当module被卸载时运行
- #define PHP_RINIT_FUNCTION ZEND_MODULE_ACTIVATE_D // 当一个REQUEST请求初始化时运行
- #define PHP_RSHUTDOWN_FUNCTION ZEND_MODULE_DEACTIVATE_D // 当一个REQUEST请求结束时运行
- #define PHP_MINFO_FUNCTION ZEND_MODULE_INFO_D // 这个是设置phpinfo中这个模块的信息
- #define PHP_GINIT_FUNCTION ZEND_GINIT_FUNCTION // 初始化全局变量时
- #define PHP_GSHUTDOWN_FUNCTION ZEND_GSHUTDOWN_FUNCTION // 释放全局变量时
MINIT -> RINIT ->RSHUTDOWN -> MSHUTDOWN
对于Session而言,PHP_MINIT_FUNCTION主要完成的初始化工作包括(注:不同版本的PHP具体处理过程并不完全相同,如PHP 5.4+提供了SessionHandlerInterface,这样可以通过session_set_save_handler ( SessionHandlerInterface $sessionhandler )的方式自定义Session的处理机制,而不必像之前一样使用冗长的boolsession_set_save_handler ( callable $open , callable $close , callable $read , callable $write , callable $destroy , callable $gc [, callable $create_sid ] )):
(1). 注册$_SESSION超全局变量:
[cpp] view plain copy
- zend_register_auto_global("_SESSION", sizeof("_SESSION")-1, NULL TSRMLS_CC);
相关阅读 :PHP语言中的超级全局变量(Superglobals) http://www.walu.cc/phpbook/12.5.md
(2). 读取ini文件中的相关配置。
[cpp] view plain copy
- REGISTER_INI_ENTRIES();
REGISTER_INI_ENTRIES();实际上是一个宏定义:
#define REGISTER_INI_ENTRIES() zend_register_ini_entries(ini_entries, module_number TSRMLS_CC)
因此,实际上是调用zend_register_ini_entries(ini_entries, module_number TSRMLS_CC)。关于ini文件的解析和配置,已经超出了本文的范畴,可以参考这篇文章:http://www.cnblogs.com/driftcloudy/p/4011954.html 。
扩展中读取和设置ini的相关配置位于PHP_INI_BEGIN和PHP_INI_END宏之间。对于session而言,实际上包括:
[cpp] view plain copy
- /* {{{ PHP_INI
- */
- PHP_INI_BEGIN()
- STD_PHP_INI_ENTRY("session.save_path", "", PHP_INI_ALL, OnUpdateSaveDir,save_path, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.name", "PHPSESSID", PHP_INI_ALL, OnUpdateName, session_name, php_ps_globals, ps_globals)
- PHP_INI_ENTRY("session.save_handler", "files", PHP_INI_ALL, OnUpdateSaveHandler)
- STD_PHP_INI_BOOLEAN("session.auto_start", "0", PHP_INI_PERDIR, OnUpdateBool, auto_start, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.gc_probability", "1", PHP_INI_ALL, OnUpdateLong, gc_probability, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.gc_divisor", "100", PHP_INI_ALL, OnUpdateLong, gc_divisor, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.gc_maxlifetime", "1440", PHP_INI_ALL, OnUpdateLong, gc_maxlifetime, php_ps_globals, ps_globals)
- PHP_INI_ENTRY("session.serialize_handler", "php", PHP_INI_ALL, OnUpdateSerializer)
- STD_PHP_INI_ENTRY("session.cookie_lifetime", "0", PHP_INI_ALL, OnUpdateLong, cookie_lifetime, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.cookie_path", "/", PHP_INI_ALL, OnUpdateString, cookie_path, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.cookie_domain", "", PHP_INI_ALL, OnUpdateString, cookie_domain, php_ps_globals, ps_globals)
- STD_PHP_INI_BOOLEAN("session.cookie_secure", "", PHP_INI_ALL, OnUpdateBool, cookie_secure, php_ps_globals, ps_globals)
- STD_PHP_INI_BOOLEAN("session.cookie_httponly", "", PHP_INI_ALL, OnUpdateBool, cookie_httponly, php_ps_globals, ps_globals)
- STD_PHP_INI_BOOLEAN("session.use_cookies", "1", PHP_INI_ALL, OnUpdateBool, use_cookies, php_ps_globals, ps_globals)
- STD_PHP_INI_BOOLEAN("session.use_only_cookies", "1", PHP_INI_ALL, OnUpdateBool, use_only_cookies, php_ps_globals, ps_globals)
- STD_PHP_INI_BOOLEAN("session.use_strict_mode", "0", PHP_INI_ALL, OnUpdateBool, use_strict_mode, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.referer_check", "", PHP_INI_ALL, OnUpdateString, extern_referer_chk, php_ps_globals, ps_globals)
- #if HAVE_DEV_URANDOM
- STD_PHP_INI_ENTRY("session.entropy_file", "/dev/urandom", PHP_INI_ALL, OnUpdateString, entropy_file, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.entropy_length", "32", PHP_INI_ALL, OnUpdateLong, entropy_length, php_ps_globals, ps_globals)
- #elif HAVE_DEV_ARANDOM
- STD_PHP_INI_ENTRY("session.entropy_file", "/dev/arandom", PHP_INI_ALL, OnUpdateString, entropy_file, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.entropy_length", "32", PHP_INI_ALL, OnUpdateLong, entropy_length, php_ps_globals, ps_globals)
- #else
- STD_PHP_INI_ENTRY("session.entropy_file", "", PHP_INI_ALL, OnUpdateString, entropy_file, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.entropy_length", "0", PHP_INI_ALL, OnUpdateLong, entropy_length, php_ps_globals, ps_globals)
- #endif
- STD_PHP_INI_ENTRY("session.cache_limiter", "nocache", PHP_INI_ALL, OnUpdateString, cache_limiter, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.cache_expire", "180", PHP_INI_ALL, OnUpdateLong, cache_expire, php_ps_globals, ps_globals)
- PHP_INI_ENTRY("session.use_trans_sid", "0", PHP_INI_ALL, OnUpdateTransSid)
- PHP_INI_ENTRY("session.hash_function", "0", PHP_INI_ALL, OnUpdateHashFunc)
- STD_PHP_INI_ENTRY("session.hash_bits_per_character", "4", PHP_INI_ALL, OnUpdateLong, hash_bits_per_character, php_ps_globals, ps_globals)
- /* Upload progress */
- STD_PHP_INI_BOOLEAN("session.upload_progress.enabled",
- "1", ZEND_INI_PERDIR, OnUpdateBool, rfc1867_enabled, php_ps_globals, ps_globals)
- STD_PHP_INI_BOOLEAN("session.upload_progress.cleanup",
- "1", ZEND_INI_PERDIR, OnUpdateBool, rfc1867_cleanup, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.upload_progress.prefix",
- "upload_progress_", ZEND_INI_PERDIR, OnUpdateSmartStr, rfc1867_prefix, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.upload_progress.name",
- "PHP_SESSION_UPLOAD_PROGRESS", ZEND_INI_PERDIR, OnUpdateSmartStr, rfc1867_name, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.upload_progress.freq", "1%", ZEND_INI_PERDIR, OnUpdateRfc1867Freq, rfc1867_freq, php_ps_globals, ps_globals)
- STD_PHP_INI_ENTRY("session.upload_progress.min_freq",
- "1", ZEND_INI_PERDIR, OnUpdateReal, rfc1867_min_freq,php_ps_globals, ps_globals)
- /* Commented out until future discussion */
- /* PHP_INI_ENTRY("session.encode_sources", "globals,track", PHP_INI_ALL, NULL) */
- PHP_INI_END()
- /* }}} */
(3). 注册SessionHandler和SessionHandlerInterface这两个Class
自php 5.4起,php提供了SessionHandler和SessionHandlerInterface这两个Class,
因此还需要对这两个Class做相关的初始化工作。这是通过:
INIT_CLASS_ENTRY(ce, PS_IFACE_NAME, php_session_iface_functions);
INIT_CLASS_ENTRY(ce, PS_CLASS_NAME, php_session_class_functions);
来实现的,有兴趣的同学可以查看具体的实现过程,这里不再赘述。
[cpp] view plain copy
- static PHP_RINIT_FUNCTION(session) /* {{{ */
- {
- return php_rinit_session(PS(auto_start) TSRMLS_CC);
- }
- /* ********************************
- * Module Setup and Destruction *
- ******************************** */
- static int php_rinit_session(zend_bool auto_start TSRMLS_DC) /* {{{ */
- {// 初始化session相关的全局变量
- php_rinit_session_globals(TSRMLS_C);
- // 根据ini的配置查找session.save_handler,从而确定是使用files还是user( 或者是其他的扩展方式)来处理session:
- if (PS(mod) == NULL) {
- char *value;
- value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0);
- if (value) {
- PS(mod) = _php_find_ps_module(value TSRMLS_CC);
- }
- }
- // 确定完session的save_handler之后。需要确定serializer,Serializer用于完成session数据的序列化和反序列化
- if (PS(serializer) == NULL) {
- char *value;
- value = zend_ini_string("session.serialize_handler", sizeof("session.serialize_handler"), 0);
- if (value) {
- PS(serializer) = _php_find_ps_serializer(value TSRMLS_CC);
- }
- }
- // mod和serializer 如果有一个不成功,更新session_status 状态
- if (PS(mod) == NULL || PS(serializer) == NULL) {
- /* current status is unusable */
- PS(session_status) = php_session_disabled;
- return SUCCESS;
- }
- // 如果ini 中 session.auto_start 为1 自动session_start
- if (auto_start) {
- php_session_start(TSRMLS_C);
- }
- return SUCCESS;
- } /* }}} */
(1).初始化session相关的全局变量,这是通过php_rinit_session_globals来完成的:
[cpp] view plain copy
- /* Dispatched by RINIT and by php_session_destroy */
- static inline void php_rinit_session_globals(TSRMLS_D) /* {{{ */
- {
- PS(id) = NULL;
- PS(session_status) = php_session_none;
- PS(mod_data) = NULL;
- PS(mod_user_is_open) = 0;
- /* Do NOT init PS(mod_user_names) here! */
- PS(http_session_vars) = NULL;
- }
- /* }}} */
(2).根据ini的配置查找session.save_handler,从而确定是使用files还是user( 或者是其他的扩展方式)来处理session:
[cpp] view plain copy
- if (PS(mod) == NULL) {
- char *value;
- value = zend_ini_string("session.save_handler", sizeof("session.save_handler"), 0);
- if (value) {
- PS(mod) = _php_find_ps_module(value TSRMLS_CC);
- }
- }
确定是user还是files来处理session的逻辑是由_php_find_ps_module来完成的,这个函数会依次查找ps_modules中预定义的module, 一旦查找成功,立即返回:
[cpp] view plain copy
- 上一篇: REDIS实践之在线人数统计几种方案分析
- 下一篇:没有了