概述
接着上篇来讲php生命周期。
php_request_startup
这个阶段和php_module_startup
差不多,都是初始化工作,比php_module_startup
简单很多,可以自己看下,重点来看下执行阶段
php_execute_script
用gdb看看调用栈,gdb ./php
在php_execute_script
打断点,执行,在看下调用栈,
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
登录后复制
在调用栈可以清楚看到执行流程,现在到/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文件看看真正的执行阶段
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;
登录后复制
加载要执行的php文件,通过zend_compile_file
进行词法分析 语法分析,生成AST
,编译成op_array
,也就是指令集,
我们看下指令集,
b zend_execute
c
bt
(gdb) p *op_array
$1 = {type = 2 '