php7.0 cli,PHP-7.1 源代码学习:php-cli 启动流程
前言
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_struct
C 語言系統編程常用手法,通過 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;
}
總結
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的php7.0 cli,PHP-7.1 源代码学习:php-cli 启动流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php添加公告代码,为wordpress
- 下一篇: php怎么调用css格式化,css文件格