接著上篇來講php生命周期。
php_request_startup
這個(gè)階段和php_module_startup
差不多,都是初始化工作,比php_module_startup
簡單很多,可以自己看下,重點(diǎn)來看下執(zhí)行階段
php_execute_script
用gdb看看調(diào)用棧,gdb ./php
在php_execute_script
打斷點(diǎn),執(zhí)行,在看下調(diào)用棧,
b php_execute_script (gdb) r test.php bt #0 php_execute_script (primary_file=0x7fffffffe240) at /www/test/php/php-7.4.3/main/main.c:2541 #1 0x00000000008bbd85 in do_cli (argc=2, argv=0x1425af0) at /www/test/php/php-7.4.3/sapi/cli/php_cli.c:961 #2 0x00000000008bcd2d in main (argc=2, argv=0x1425af0) at /www/test/php/php-7.4.3/sapi/cli/php_cli.c:1356
在調(diào)用??梢郧宄吹綀?zhí)行流程,現(xiàn)在到/cli/php_cli.c文件看看做了哪些事情,
int c; zend_file_handle file_handle; int behavior = PHP_MODE_STANDARD; char *reflection_what = NULL; volatile int request_started = 0; volatile int exit_status = 0; char *php_optarg = NULL, *orig_optarg = NULL; int php_optind = 1, orig_optind = 1; char *exec_direct=NULL, *exec_run=NULL, *exec_begin=NULL, *exec_end=NULL; char *arg_free=NULL, **arg_excp=&arg_free; char *script_file=NULL, *translated_path = NULL; int interactive=0; int lineno = 0; const char *param_error=NULL; int hide_argv = 0; zend_try { CG(in_compilation) = 0; /* not initialized but needed for several options */ while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) { switch (c) {
初始化變量,解析命令到/main/main.c文件看看真正的執(zhí)行階段
PHPAPI int php_execute_script(zend_file_handle *primary_file) { zend_file_handle *prepend_file_p, *append_file_p; zend_file_handle prepend_file = {{0}, NULL, NULL, 0, 0}, append_file = {{0}, NULL, NULL, 0, 0}; #if HAVE_BROKEN_GETCWD volatile int old_cwd_fd = -1; #else char *old_cwd; ALLOCA_FLAG(use_heap) #endif int retval = 0;
加載要執(zhí)行的php文件,通過zend_compile_file
進(jìn)行詞法分析 語法分析,生成AST
,編譯成op_array
,也就是指令集,
我們看下指令集,
b zend_execute c bt (gdb) p *op_array $1 = {type = 2 '