知识准备:
1 PHP源码主要结构:
README.XXX 帮助文件
Build 编译相关文件
Ext php的各种函数的实现
Main 实现php的核心架构代码,不包含底层中间代码的解析
Zend 中间代码opcode的相关逻辑及底层执行实现
Pear php相关扩展库
Sapi 各种服务器抽象层的代码
TSRM 线程相关库
Tests 测试用例
Win32 windows平台相关的代码
2 启动php的模式(主要接口代码在sapi中)
服务器模式
Apache: php_mod, fastcgi
Php_mod:作为apache的一个扩展模块进行php脚本的解析
fastcgi:通过fastcgi协议进行php脚本的解析
Nginx : fastcgi
剩下的服务器模式感觉不是那么主流,先不管了
phpcli模式
命令行运行模式,从命令行中执行php脚本就切到这里了
嵌入式模式
这个实际应该比较稀有,先放着吧
3 各个模式的启动流程
Mint -> rint -> script-> rshutdown -> mshutdown
模块初始化 -> 请求初始化 ->处理具体的业务 -> 关闭请求 -> 关闭模块
在非cli模式下,mint 将在服务器启动阶段进行,当请求到达时,不在启动mint,直接进行rint阶段,处理完请求执行rshutdown
同样,每个请求也并不执行mshutdown,这个行为在服务器关闭或重启时统一一次调用。
cli模式可能是个例外,他还是需要每次都载入模块的,即执行mint
开始正文:
以cli模式为例(这样就不用牵扯到服务器了),我们先走一圈
启动代码在 sapi/cli/php_cli.c中
代码从main函数开始启动
主体运行流程:
填充sapi模块的结构
这里定义的sapi_module_struct为cli_sapi_module。
启动sapi,进行sapi的一些全局设置
sapi_startup(&cli_sapi_module)
运行sapi模块的startup,对各种模块,扩展,资源进行注册和初始化
cli_sapi_module.startup(&cli_sapi_module)
这里面各种startup和register,例如几个重要的
php_module_startup()
zend_startup(&zuf, NULL TSRMLS_CC);zend_startup_modules(TSRMLS_C);
zend_startup_extensions();
初始化请求
执行php_request_startup();
编译php文件,把编译后的opcode执行
php_execute_script(&file_handle TSRMLS_CC);
这里面的编译命令为
EG(active_op_array) = zend_compile_file(file_handle, type TSRMLS_CC);实际调用的是zend_language_scanner.c里面的
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC)
这里最终的执行命令为
zend_execute(EG(active_op_array) TSRMLS_CC);实际调用的是
Zend_vm_excute.h里面的
ZEND_API void execute(zend_op_array *op_array TSRMLS_DC)
请求关闭释放的相关工作
执行php_request_shutdown();
关闭释放相关的各种模块
php_module_shutdown(TSRMLS_C);
关闭sapi相关资源
sapi_shutdown();
Ps:
常听人说php源代码比较乱,感觉跟nginx代码比起来。。的确有些让人郁闷很多。。