摘要:前言函数默认构建目标为,相关代码在目录下,文件中能够找到入口函数,大概流程如下命令行参数处理初始化清理工作语言系统编程常用手法,通过中声明函数指针类型的字段来实现类似面向对象中抽象类的概念,在文件中可以找到该结构体的定义,这里只列出部分
前言 php cli main 函数
configure & make 默认构建目标为 php-cli,相关代码在 sapi/cli 目录下,php_cli.c 文件中能够找到 main(入口)函数,大概流程如下:
命令行参数处理
cli_sapi_module 初始化
sapi_module->startup
do_cli or do_cli_server
清理工作
sapi_module_structC 语言系统编程常用手法,通过 struct 中声明 函数指针 类型的字段来实现类似面向对象中抽象类的概念,在 main/SAPI.h 文件中可以找到该结构体的定义,这里只列出部分字段(下同):
struct _sapi_module_struct { char *name; char *pretty_name; int (*startup)(struct _sapi_module_struct *sapi_module); int (*shutdown)(struct _sapi_module_struct *sapi_module); ... char *ini_entries; const zend_function_entry *additional_functions; unsigned int (*input_filter_init)(void); }cli_sapi_module
cli_sapi_module 是一个静态全局变量,定义在 php_cli.c 中,你可以将它理解成是 sapi_module_struct "类" 的一个 "实例",结构体中 "挂载" 了 cli 特定的实现函数:
/* {{{ sapi_module_struct cli_sapi_module */ static sapi_module_struct cli_sapi_module = { "cli", /* name */ "Command Line Interface", /* pretty name */ ... php_cli_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ ... STANDARD_SAPI_MODULE_PROPERTIES };do_cli
do_cli 函数定义在 php_cli.c 文件中,大致流程如下:
根据命令行选项 确定 behavior(解释器行为)
根据 behavior 执行相应的动作
通过执行 sapi/cli/php --help 可以查看所有的 php-cli 命令行选项,我们通过几个简单的选项来分析解释器执行流程
PHP_MODE_CLI_DIRECT该模式下,php-cli 会执行解释执行通过命令行参数传递的 code
case PHP_MODE_CLI_DIRECT: cli_register_file_handles(); if (zend_eval_string_ex(exec_direct, NULL, "Command line code", 1) == FAILURE) { exit_status=254; } break;
追踪 zend_eval_string_ex 的函数调用,定位到 zend_execute_API.c 文件中 zend_eval_stringl 函数,代码逻辑已经很清楚了:先调用 zend_compile_string 函数编译代码生成字节码 new_op_array,再调用 zend_execute 函数执行生成的字节码
ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name) { ... original_compiler_options = CG(compiler_options); CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL; new_op_array = zend_compile_string(&pv, string_name); CG(compiler_options) = original_compiler_options; if (new_op_array) { zend_try { ZVAL_UNDEF(&local_retval); zend_execute(new_op_array, &local_retval); } zend_catch { destroy_op_array(new_op_array); efree_size(new_op_array, sizeof(zend_op_array)); zend_bailout(); } zend_end_try(); ... } else { retval = FAILURE; } zval_dtor(&pv); return retval; }
zend_compile_string 属于语法分析内容,参考 PHP-7.1 源代码学习: 语法分析,这里做个简要介绍
compile_string通过搜索源代码可以发现 zend_compile_string 最终调用 compile_string
zend_op_array *compile_string(zval *source_string, char *filename) { zend_lex_state original_lex_state; zend_op_array *op_array = NULL; zval tmp; if (Z_STRLEN_P(source_string)==0) { return NULL; } ZVAL_DUP(&tmp, source_string); convert_to_string(&tmp); source_string = &tmp; zend_save_lexical_state(&original_lex_state); if (zend_prepare_string_for_scanning(source_string, filename) == SUCCESS) { BEGIN(ST_IN_SCRIPTING); op_array = zend_compile(ZEND_EVAL_CODE); } zend_restore_lexical_state(&original_lex_state); zval_dtor(&tmp); return op_array; }总结
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/22325.html
摘要:前言本文通过分析这个语句的编译和执行来窥探解释执行逻辑准备参考之前的系列文章,在环境下下载,编译源代码将代码导入中编辑运行选项,增加运行参数设置断点开始调试是一个测试脚本,放在目录下,中只包含一条简单的赋值语句调用堆栈参考之前的系列文章 前言 本文通过分析 $a=1 这个 PHP 语句的编译和执行来窥探 php-cli 解释执行逻辑 准备 参考之前的系列文章,在 ubuntu 环境下...
摘要:配置例如文件的目录关系如下打开文件,修改的值为项目文件的相对路径,这个路径会映射到容器的目录上,注意任何修改配置文件都需要执行容器名字重新构建相关容器。 背景 每次更换一个工作用的电脑,都需要很长的时间来搭建本地的运行环境。有时候,为了安装一个扩展会折腾半天,而且可能需要安装多个版本的 php。有人说,集成运行环境不是很好嘛,一次搞定所有的要求。是的,对于新手来说,使用集成包就足够了。...
摘要:前言字节码生成编译的代码主要集中在,文件中包含大量的函数,基本上一个函数对应语法规则文件一个非终结符,函数是所有函数的入口数据结构结构体是字节码抽象结构体并没有像名字那样简单,它包含了大量的字段供虚拟机在运行时使用一如既往的简单,直观,相比 前言 字节码生成(编译)的代码主要集中在 zend_compile.c ,文件中包含大量的 zend_compile_xxx 函数,基本上一个函数...
摘要:开场白作为一个技术团队的,你是如何保证成员的开发环境达到公司的标准,或者是你定制的最低要求的如果你的回答是差不多就行了,有问题再说,那么,你已经在给自己挖坑了。好的,成员们开始构建你定制的开发环境了。 开场白 作为一个技术团队的Leader,你是如何保证成员的开发环境达到公司的标准,或者是你定制的最低要求的?如果你的回答是:差不多就行了,有问题再说,那么,你已经在给自己挖坑了。 同事A...
阅读 1970·2021-11-23 10:03
阅读 4129·2021-11-22 09:34
阅读 2466·2021-10-08 10:05
阅读 2245·2019-08-30 15:53
阅读 1686·2019-08-30 13:56
阅读 1149·2019-08-29 16:52
阅读 1102·2019-08-26 13:31
阅读 3345·2019-08-26 11:45