设为首页 收藏本站
查看: 453|回复: 0

[经验分享] 原:PHP的执行流程,PHP扩展加载过程

[复制链接]

尚未签到

发表于 2017-3-20 14:23:27 | 显示全部楼层 |阅读模式
声明:本文为
斯人
原创,全部为作者一一分析得之,有不对的地方望赐教。

欢迎转载,转载请注明出处 。

  
本文地址:
http://imsiren.com/archives/535
  
为了以后能够明白的开发PHP扩展..就一定要了解PHP的执行顺序..这篇文章就是为C开发PHP扩展做铺垫.

web环境 我们假设为 apache.

在编译PHP的时候,为了能够让Apache支持PHP,我们会生成一个mod_php5.so的模块.apache加载这个模块..

在url访问.php文件的时候就会转给mod_php5.so模块来处理.这个玩意是什么..就是我们常说的SAPI

英文名字是:Server abstraction API.

SAPI说的其实是一个统称,其下有 ISAPI,CLI SAPI, CGI等.

有了它,就可以很容易的跟其他东西交互.比如APACHE,IIS,CGI等.

好了回到正题.

apache启动后会将mod_pho5.so模块的hook handler注册进来.apache今天不是主角,所以不细说.

当APACHE检测到 访问的url是一个php文件时,这时候就会把控制权交给sapi.

进入到sapi后,首先会执行sapi/apache/mod_php5.c 文件的php_init_handler函数


  

static void php_init_handler(server_rec *s, pool *p){register_cleanup(p, NULL, (void (*)(void *))apache_php_module_shutdown_wrapper, (void (*)(void *))php_module_shutdown_for_exec);if (!apache_php_initialized) {apache_php_initialized = 1;#ifdef ZTStsrm_startup(1, 1, 0, NULL);#endifsapi_startup(&apache_sapi_module);php_apache_startup(&apache_sapi_module);}#if MODULE_MAGIC_NUMBER >= 19980527{TSRMLS_FETCH();if (PG(expose_php)) {ap_add_version_component("PHP/" PHP_VERSION);}}#endif}
该函数主要调用 两个函数

sapi_startup(&apache_sapi_module);

php_apache_startup(&apache_sapi_module);

  

SAPI_API void sapi_startup(sapi_module_struct *sf){sf->ini_entries = NULL;sapi_module = *sf;.................sapi_globals_ctor(&sapi_globals);................virtual_cwd_startup(); /* Could use shutdown to free the main cwd but it would just slow it down for CGI */..................reentrancy_startup();}
sapi_startup创建一个 sapi_globals_struct结构体.

sapi_globals_struct保存了apache请求的基本信息,如服务器信息,header,编码等.

  


  

static void sapi_globals_ctor(sapi_globals_struct *sapi_globals TSRMLS_DC){memset(sapi_globals, 0, sizeof(*sapi_globals));zend_hash_init_ex(&sapi_globals->known_post_content_types, 5, NULL, NULL, 1, 0);php_setup_sapi_content_types(TSRMLS_C);}
known_post_content_types是一个HashTable,将其大小初始化为5.从字面意义上我猜测它保存的应该是客户端传递过来的内容类型.

php_setup_sapi_content_types函数将sapi_post_entry添加到sapi_globals里

sapi_startup执行完毕后再执行php_apache_startup

  

static int php_apache_startup(sapi_module_struct *sapi_module){if (php_module_startup(sapi_module, &apache_module_entry, 1) == FAILURE) {return FAILURE;} else {return SUCCESS;}}
php_module_startup 内容太多..是介绍一下作用.

1. 初始化zend_utility_functions 结构.这个结构是设置zend的函数指针,比如错误处理函数,输出函数,流操作函数等.

2. 设置环境变量.

3. 加载php.ini配置.

4. 加载php内置扩展.

5. 写日志.

6. 注册php内部函数集.

7. 调用 php_ini_register_extensions,加载所有外部扩展

8. 开启所有扩展

9. 一些清理操作.

重点说一下 3,4,7,8

加载php.ini配置

if (php_init_config(TSRMLS_C) == FAILURE) {

return FAILURE;

}

php_init_config函数会在这里检查所有php.ini配置,并且找到所有加载的模块,添加到php_extension_lists结构中.

加载php内置扩展

调用 zend_register_standard_ini_entries加载所有php的内置扩展,如array,mysql等.

调用php_ini_register_extensions,加载所有外部扩展

main/php_ini.c

  


  

void php_ini_register_extensions(TSRMLS_D){zend_llist_apply(&extension_lists.engine, php_load_zend_extension_cb TSRMLS_CC);zend_llist_apply(&extension_lists.functions, php_load_php_extension_cb TSRMLS_CC);zend_llist_destroy(&extension_lists.engine);zend_llist_destroy(&extension_lists.functions);}
zend_llist_apply函数遍历extension_lists 执行会掉函数 php_load_php_extension_cb

php_load_php_extension_cb
static void php_load_zend_extension_cb(void *arg TSRMLS_DC){zend_load_extension(*((char **) arg));}
调用 ext/standard/dl.c zend_load_extension 加载扩展,

该函数略过..

该函数最后调用

if ((module_entry = zend_register_module_ex(module_entry TSRMLS_CC)) == NULL) {

DL_UNLOAD(handle);

return FAILURE;

}

将 扩展信息 放到 Hash表module_registry中

Zend/zend_API.c

  

if (zend_hash_add(&module_registry, lcname, name_len+1, (void *)module, sizeof(zend_module_entry), (void**)&module_ptr)==FAILURE) {zend_error(E_CORE_WARNING, "Module '%s' already loaded", module->name);efree(lcname);return NULL;}
最后
zend_startup_modules(TSRMLS_C); //对模块进行排序,并检测是否注册到module_registry HASH表里

zend_startup_extensions(); //执行extension->startup(extension);启动扩展…

WOW……….都半夜12点了…我的天.整整分析了三个小时…
就到这里吧…

原文出处:http://imsiren.com/archives/535

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-352535-1-1.html 上篇帖子: 什么是CGI、FastCGI、PHP-CGI、PHP-FPM、Spawn-FCGI? 下篇帖子: PHP获得URL路径
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表