PHP程序执行的过程原理
为了以后能开发PHP扩展,就一定要了解PHP的执行顺序。这篇文章就是为C开发PHP扩展做铺垫。
Web环境我们假设为Apache。在编译PHP的时候,为了能够让Apache支持PHP,我们会生成一个mod_php5.so的模块。Apache加载这个模块,在url访问.php文件的时候,就会转给mod_php5.so模块来处理。
这个就是我们常说的SAPI。英文名字是:Server Application Programming Interface。SAPI其实是一个统称,其下有 ISAPI,CLI SAPI,CGI等。有了它,就可以很容易的跟其他东西交互,比如APACHE,IIS,CGI等。
Apache启动后会将mod_pho5.so模块的hook handler注册进来,当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 = ;
#ifdef ZTS
tsrm_startup(, , , NULL);
#endif
sapi_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);
static int php_apache_startup(sapi_module_struct *sapi_module)
{
if (php_module_startup(sapi_module, &apache_module_entry, ) == FAILURE) {
return FAILURE;
} else {
return SUCCESS;
}
}
sapi_startup创建一个 sapi_globals_struct结构体。sapi_globals_struct保存了Apache请求的基本信息,如服务器信息,Header,编码等。sapi_startup执行完毕后再执行php_apache_startup。
static int php_apache_startup(sapi_module_struct *sapi_module)
{
if (php_module_startup(sapi_module, &apache_module_entry, ) == 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
static void php_load_zend_extension_cb(void *arg TSRMLS_DC)
{
zend_load_extension(*((char **) arg));
}
该函数最后调用
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+, (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);启动扩展。
PHP程序执行的过程原理的更多相关文章
- Java程序执行的过程
ava程序执行的过程: Step1:将字节码加入内存: Step2:对字节码进行合法性检查: Step3:jvm会为每个字节码文件都生成一个对象(class): Step4:执行静态代码块,初始化静态 ...
- [转载]JAVA内存分析——栈、堆、方法区 程序执行变化过程
面向对象的内存分析 参考:http://www.sxt.cn/Java_jQuery_in_action/object-oriented.html :尚学堂JAVA300集-064内存分析详解_栈_堆 ...
- 一起talk GDB吧(第六回:GDB改动程序执行环境)
各位看官们,大家好,上一回中我们说的是GDB查看信息的功能,而且说了怎样使用GDB查看程序执行时的 信息.这一回中,我们继续介绍GDB的调试功能:改动程序执行环境.当然了,我们也会介绍怎样使用GDB ...
- 程序执行的过程分析--【sky原创】
程序执行的过程: 比如我们要执行3 + 2 程序计数器(PC) = 指令地址 指令寄存器(IR) = 正在执行的命令 累加器(AC) = 临时存储体 那么实际上执行了三条指令 每条指令 ...
- Python程序的执行过程原理(解释型语言和编译型语言)
Python是一门解释型语言?我初学Python时,听到的关于Python的第一句话就是Python是一门解释型语言,我就这样一直相信下去,直到发现.pyc文件的存在,如果真是解释型语言,那么生成的. ...
- iOS程序启动的过程及原理
iOS程序启动的过程及原理 文字部分 先执行main函数,main内部会调用UIApplicationMain函数 UIApplicationMain函数里面做了什么事情??? 1> 创建UIA ...
- python笔记:#006#程序执行原理
程序执行原理(科普) 目标 计算机中的 三大件 程序执行的原理 程序的作用 01. 计算机中的三大件 计算机中包含有较多的硬件,但是一个程序要运行,有 三个 核心的硬件,分别是: CPU 中央处理器, ...
- Web APi之过滤器执行过程原理解析【二】(十一)
前言 上一节我们详细讲解了过滤器的创建过程以及粗略的介绍了五种过滤器,用此五种过滤器对实现对执行Action方法各个时期的拦截非常重要.这一节我们简单将讲述在Action方法上.控制器上.全局上以及授 ...
- Android入门学习:Android 系统框架及应用程序执行过程
Android基础知识学习 新手上路,还请多多帮助.由于初学,博客内容难免有不正确的地方,还请各位多多指教,相互学习! 主要内容: 1.Android层次架构及主要功能 2.Android编程模型,程 ...
随机推荐
- 备战“金九银十”10道String高频面试题解析
前言 String 是我们实际开发中使用频率非常高的类,Java 可以通过 String 类来创建和操作字符串,使用频率越高的类,我们就越容易忽视它,因为见的多所以熟悉,因为熟悉所以认为它很简单,其实 ...
- CCF-CSP题解 201703-3 Markdown
要求实现简易的Markdown到Html格式的转换. 主要就是字符串处理.以空行划分各个区块,区块内部字符的输出用一个\(print\_buf\)实现,至于强调和超链接的嵌套,则可以递归实现. 注意用 ...
- 利用 DFA 算法实现文字过滤
一.DEA 算法简介 在实现文字过滤的算法中,DFA是唯一比较好的实现算法. DFA 全称为:Deterministic Finite Automaton,即确定有穷自动机.其特征为:有一个有限状态集 ...
- 超级详细Mysql安装步骤图解
数据库忘记装了,然后今天才装上.刚开始有点蒙蔽,进入mysql官网一堆英文,小声逼逼没有学号英语的我.废话不都说,直接上图 1.输入网址 https://www.mysql.com/downloads ...
- ORA-27140: attach to post/wait facility failed
Errors in file /home/u01/app/oracle/diag/rdbms/hnybdb21/hnybdb211/trace/hnybdb211_j000_143099.trc:OR ...
- django补充CBV和FBV模式
django补充CBV和FBV模式FBV模式---函数:经常用的方式CBV模式---类CBV中url连接时函数名后面要接.as_view()class index(views.View): @... ...
- C#线程学习笔记一:线程基础
本笔记摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/18/Thread.html,记录一下学习过程以备后续查用. 一.线程的介绍 进程(Proce ...
- golang的缓冲channel简单使用
目录 golang的缓冲channel简单使用 阻塞型 非阻塞 golang的缓冲channel简单使用 我们常用的是无缓冲channel : make(chan type) 其实make() 创建c ...
- phpmyadmin 4.8.1 远程文件包含漏洞(CVE-2018-12613)
漏洞详情 范围 phpMyAdmin 4.8.0和4.8.1 原理 首先在index.php 50-63行代码 $target_blacklist = array ( 'import.php', 'e ...
- MAT分析android内存泄漏
转载请标明出处:https://www.cnblogs.com/tangZH/p/10955429.html 泄漏,泄漏,漏~ 内存泄漏怎么破,什么是内存泄漏?与内存溢出有什么区别? 内存泄漏(Mem ...